Rewrite timer communication to use a state machine and structs.
free() timer struct during cleanup.
Split thread shutdown notification / join.
Rewrite fatal error handling and shutdown.

 - The fatal error dialog is now a panel that displays
   over the main window
 - The main window remains open and the log is updated
   with the current status while waiting for worker
   threads to terminate.