[ImageJ-devel] ImageJ quits twice

Curtis Rueden ctrueden at wisc.edu
Wed Aug 6 16:19:43 CDT 2014


Hi everyone,

Today I spent some time fixing a new quitting-related bug in ImageJ2: the
"ImageJ quits twice" bug. This was an OS-X-specific bug, related to the Mac
application menu handling.

When quitting via Apple > Quit (or Cmd+Q), ImageJ would show two different
sets of dialogs: the usual ones, and another one that said simply "Quit
ImageJ?" with OK/Cancel. Relatedly, ImageJ would also show two About
dialogs when you say Apple > About, and take two different actions when you
say Apple > Preferences. In a nutshell, this unfortunate behavior was
because both ImageJ 1.x and ImageJ2 were trying to handle those actions.

The problem has now been fixed, and made it onto the respective master
branches, as follows:

EventHandler: add optional key attribute
https://github.com/scijava/scijava-common/commit/bdf746798cbea51fddc4822f220bba2d909be0b8

Which makes possible:

DefaultAppEventService: specify subscription keys
https://github.com/scijava/scijava-common/commit/6b1fd5fc3c7f00f8d443d2447f72b016caf378f1

Which makes the following fully work:

Fix the "Fiji quits twice" bug ;-)
https://github.com/imagej/imagej-legacy/commit/a9cfa620f694dd7af8d0224d399b47adaef20942

Please note that these fixes have _not_ been uploaded to the Updater yet,
but we will do so as soon as we can. There will be a slew of releases by
the end of this week.

Regards,
Curtis

P.S. For the very technically inclined (*squints at Dscho*), as well as the
archives:

I want to describe one detail while it's still fresh in my mind. In the
SciJava Common application framework, if you have multiple services that
implement the same service interface, both annotated with "@Plugin(type =
Service.class)", then a full-blown application context will instantiate one
of each. _However_, if one of them extends the other, the story is
different. In the case of AppEventService, there is a
DefaultAppEventService in scijava-common, a CoreAppEventService in
imagej-plugins-commands and now a LegacyAppEventService in imagej-legacy.
Both of the latter two extend the Default one. Hence, when the Context is
initializing its services, it creates them in priority order: 1)
LegacyAppEventService [high]; 2) CoreAppEventService [normal]; and 3)
DefaultAppEventService [low]. Except that when it is time to create the
DefaultAppEventService, the ServiceHelper skips creating it because there
is already one present in the context. _Two_, actually!

This has a weird ramification on event handling. As long as we had only
CoreAppEventService and DefaultAppEventService, there is only one
AppEventService instance in the context, so only one receives the
App*Events, so all is well. As soon as we added LegacyAppEventService,
though, suddenly a full context has _two_ different AppEventService
implementations, _both_ of which are receiving the App*Event notifications.
So each of them was trying to handle the events, resulting in the double
quit behavior.

The fix is described in the GitHub links above. We might need to make _all_
@EventHandler methods have some default non-empty key based on their class
and method signature. Otherwise, it will only be possible to override
behavior of EventHandler methods that take care to provide such a key.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://imagej.net/pipermail/imagej-devel/attachments/20140806/1627a81a/attachment.html>


More information about the ImageJ-devel mailing list