getlantern/systray

Terminating process leaves icon visible

andrewfstratton opened this issue · 4 comments

(Run on Win 11)

When I terminate the go application - the tray icon is left visible in the sys tray (possibly off screen) and will remain there until mouse over - it then disappears. This happens when:

  • the application is built, then the 'exe' is run from the command line, then Ctrl-C used to kill the application. Note that the application is removed from the Task Manager
  • or using VS Code to stop/restart the application

If I run the application several times and keep restarting, a new icon is generated every time - where only the latest one is a valid running application.

Note: this is not to do with properly exited (quit) applications - which works fine - but when the process is terminated, it seems the icon is not tidied up.

This sounds like your application is not handling Ctrl-C and performing cleanup, but I could be wrong. Killing the app with VSCode will also not let the app do any cleanup it needs to do. Any time you unceremoniously kill an app that has an icon in the system tray, the icon will get left behind; at least that's my experience.

That is exactly correct - I guess you're saying that systray won't tidy up after itself - and the example code in the Readme.md also has the same issue (I think).

Could/should systray maybe handle an OS Interrupt and exit gracefully?

I tried adding a handler for Ctrl C - see below (modified from https://golangcode.com/handle-ctrl-c-exit-in-terminal/).

The output after hitting Ctrl-C in the command line shows (correctly) Quit... then Exit..., but again, the icon still remains in the system tray until I mouse over it - then it disappears. So calling systray.Quit() doesn't seem to tidy up the icon.

I then checked quitting through the systray menu - and the icon only disappears if I happen to have the mouse over the icon at the time...so this doesn't seem to work either.

Any help/suggestions please?

func Run() {
	// handle OS interrupt
	interrupt_channel := make(chan os.Signal)
	signal.Notify(interrupt_channel, os.Interrupt)
	go handleInterrupt(interrupt_channel)
	// N.B. next line blocks until quit...
	systray.Run(setup, close)
}

func handleInterrupt(interrupt chan os.Signal) {
	<-interrupt
	fmt.Println("Quit...")
	systray.Quit()
	fmt.Println("Exit...")
	os.Exit(0)
}

Solved - I added a 1 second delay after systray.Quit() before closing everything else down - and the icon disappears correctly...i.e. after menu quitting and after Ctrl-C.

So it looks like systray.Quit() doesn't get enough time to tidy up if you just exit the application. Possibly this could be fixed by making it return only when the icon has been removed (?).

Still doesn't work when VSCode halts and then kills the application - but I can live with that :)