Il problema come lo hai affrontato secondo me è corretto, ma mostra la debolezza proprio nel momento in cui non viene scaturito l'evento onunload.

Proprio per educare l'utente quello che ti ho proposto è un metodo che potrebbe funzionare.

Nel momento in cui l'utente titolare dello username e password viene sbattuto fuori puoi mostrare un messaggio che spiega che i motivi possono essere dovuti ad un malfunzionamento e in tal caso mostri l'email per il supporto (ma tu sai che questo caso non si pone a meno che la password non sia stata effettivamente trafugata), oppure al fatto che qualcun'altro stia accedendo con lo stesso username e password (instillando il dubbio che forse cedere il proprio username e password non è una pratica corretta).

Alternativamente potresti procedere come hai fatto fin'ora, pensando ad una procedura chiamata via cron che cancelli lo stato di loggato quando il file di sessione non esiste più (in fase di login memorizzi su db l'id di sessione, che ti permette di risalire al file dove vengono memorizzate appunto le sessioni).
Questo però ti porterebbe necessariamente ad un periodo in cui l'utente non può loggarsi (ad esempio avviene una disconnessione, l'utente chiude il browser - quindi non ha più lo stesso id di sessione e quando si riconnette non può loggarsi finche la procedura non rilevi che il file di sessione non esiste più).

Per il momento altre soluzioni non me ne vengono in mente.

Ciao