I took a look at bug #27786 "screenshot plugin on Solaris takes bus
error on exit" because I wanted to see if I could reproduce it.  Well,
I got another problem: the screenshot plug-in exits with "xwd didn't
work" before giving any results.  If my followup message makes it to
#27786 (http://bugs.gnome.org/db/27/27786.html), you will read that
xwd does work but the plug-in thinks that it doesn't.  As a result, it
exits prematurely and leaves the temporary files in the user's dir.

I tried to debug this and I finally came to the conclusion that
waitpid() fails because the SIGCHLD signal handler installed by
libgimp steals the return status of the xwd child before waitpid() in
screenshot.c has a chance to get it.  In libgimp/gimp.c, the signal
handler gimp_plugin_sigchld_handler() calls waitpid() in a loop and
throws away the child status before returning.

In order to test this, I added some code in screenshot.c that calls
gimp_signal_private() and installs an empty SIGCHLD handler before
forking (SIG_DFL also works, but not SIG_IGN).  As a result,
everything worked and I was able to get the screenshots without any
problems.

Now I understand Marc's frustration when he said a few months ago that
libgimp should not install any signal handlers if the plug-ins don't
want to.  A clean solution would have been to add a new call such as
gimp_plugin_install_default_signal_handlers_please() and change all
plug-ins (except for perl and screenshot) so that they call this when
they are started, but changing all plug-ins now is probably a bit too
late.  Now, the easiest workaround for the plug-ins that do not like
the handlers installed by libgimp is to reset the signals to SIG_DFL
or to install new handlers.

I think that the best way to fix the screenshot plug-in is to add this
before the call to fork():
  gimp_signal_private (SIGCHLD, SIG_DFL, SA_RESTART);
(don't forget to #include <libgimp/gimpsignal.h>)

I am surprised that the screenshot plug-in seems to work under Linux.
This is probably because Solaris calls the SIGCHLD handler before
returning from the blocking waitpid(), while Linux returns from the
blocking waitpid() before calling the signal handler.  If this is the
case, then the plug-in works under Linux only because we are lucky,
and may fail with any other OS.

If you are reading this and using HP-UX, IRIX, AIX or any other UNIX,
please test it!  The two-lines patch described above should fix this
bug.

-Raphael

Reply via email to