diff --git a/ChangeLog b/ChangeLog index 1d2181f291..165f49d235 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,28 @@ +2000-04-21 Garry R. Osgood + + * app/main.c + * libgimp/Makefile.am + * libgimp/gimp.c + * libgimp/gimpsignal.c (New ) + * libgimp/gimpsignal.h (New ) + Patch by Austin Donnelly to address #2742. (I took + the liberty of moving it to libgimp for general consumption, & fixed a + typo) SYS5R4 unix's were failing when signals arrived at processes in + system calls, a behavior in accordance with POSIX specs. Patch + introduces a gimp_signal_private() workalike replacement for + signal(2), layered over sigaction(2) which internally requests the + signal environment to restart system calls instead of failing. This is + POSIX spec 1170 extension behavior, but one that appears to be generally + supported. Thanks due to Tim Mooney + for testing this on various flavors of OSF/1 boxes where #2742 seemed + especially common. + 2000-04-20 Nick Lamb - * plug-ins/common/png.c: Revert Sven's changes, I am not that - silly Sven, read the code more carefully and THINK about it. - We do not want to leak Gimp Images. + * plug-ins/common/png.c: Revert Sven's changes, I am + not that silly Sven, read the code more carefully + and THINK about it. We do not want to leak Gimp + Images. 2000-04-20 Sven Neumann diff --git a/app/main.c b/app/main.c index c29e14434f..3deb0a34a9 100644 --- a/app/main.c +++ b/app/main.c @@ -40,6 +40,10 @@ #include "libgimp/gimpfeatures.h" #include "libgimp/gimpenv.h" +#ifndef G_OS_WIN32 +#include "libgimp/gimpsignal.h" +#endif + #include "appenv.h" #include "app_procs.h" #include "errors.h" @@ -50,11 +54,10 @@ #ifdef G_OS_WIN32 #include #else -static RETSIGTYPE on_signal (gint); -#ifdef SIGCHLD -static RETSIGTYPE on_sig_child (gint); -#endif +void on_signal (gint); +void on_sig_child (gint); #endif + static void init (void); static void on_error (const gchar *domain, GLogLevelFlags flags, @@ -316,6 +319,7 @@ main (int argc, g_set_message_handler ((GPrintFunc) gimp_message_func); #ifndef G_OS_WIN32 + /* No use catching these on Win32, the user won't get any * stack trace from glib anyhow. It's better to let Windows inform * about the program error, and offer debugging (if the use @@ -324,38 +328,20 @@ main (int argc, */ /* Handle some signals */ -#ifdef SIGHUP - signal (SIGHUP, on_signal); -#endif -#ifdef SIGINT - signal (SIGINT, on_signal); -#endif -#ifdef SIGQUIT - signal (SIGQUIT, on_signal); -#endif -#ifdef SIGABRT - signal (SIGABRT, on_signal); -#endif -#ifdef SIGBUS - signal (SIGBUS, on_signal); -#endif -#ifdef SIGSEGV - signal (SIGSEGV, on_signal); -#endif -#ifdef SIGPIPE - signal (SIGPIPE, on_signal); -#endif -#ifdef SIGTERM - signal (SIGTERM, on_signal); -#endif -#ifdef SIGFPE - signal (SIGFPE, on_signal); -#endif -#ifdef SIGCHLD + gimp_signal_syscallrestart (SIGHUP, on_signal); + gimp_signal_syscallrestart (SIGINT, on_signal); + gimp_signal_syscallrestart (SIGQUIT, on_signal); + gimp_signal_syscallrestart (SIGABRT, on_signal); + gimp_signal_syscallrestart (SIGBUS, on_signal); + gimp_signal_syscallrestart (SIGSEGV, on_signal); + gimp_signal_syscallrestart (SIGPIPE, on_signal); + gimp_signal_syscallrestart (SIGTERM, on_signal); + gimp_signal_syscallrestart (SIGFPE, on_signal); + /* Handle child exits */ - signal (SIGCHLD, on_sig_child); -#endif + + gimp_signal_syscallrestart (SIGCHLD, on_sig_child); #endif @@ -414,11 +400,13 @@ on_error (const gchar *domain, gimp_fatal_error ("%s", msg); } -static gboolean caught_fatal_sig = FALSE; - #ifndef G_OS_WIN32 -static RETSIGTYPE +/* gimp core signal handler for fatal signals */ + +static gboolean caught_fatal_sig = FALSE; + +static void on_signal (gint sig_num) { if (caught_fatal_sig) @@ -427,59 +415,52 @@ on_signal (gint sig_num) switch (sig_num) { -#ifdef SIGHUP + case SIGHUP: gimp_terminate ("sighup caught"); break; -#endif -#ifdef SIGINT + case SIGINT: gimp_terminate ("sigint caught"); break; -#endif -#ifdef SIGQUIT + case SIGQUIT: gimp_terminate ("sigquit caught"); break; -#endif -#ifdef SIGABRT + case SIGABRT: gimp_terminate ("sigabrt caught"); break; -#endif -#ifdef SIGBUS + case SIGBUS: gimp_fatal_error ("sigbus caught"); break; -#endif -#ifdef SIGSEGV + case SIGSEGV: gimp_fatal_error ("sigsegv caught"); break; -#endif -#ifdef SIGPIPE + case SIGPIPE: gimp_terminate ("sigpipe caught"); break; -#endif -#ifdef SIGTERM + case SIGTERM: gimp_terminate ("sigterm caught"); break; -#endif -#ifdef SIGFPE + case SIGFPE: gimp_fatal_error ("sigfpe caught"); break; -#endif + default: gimp_fatal_error ("unknown signal"); break; } } -#ifdef SIGCHLD -static RETSIGTYPE +/* gimp core signal handler for death-of-child signals */ + +static void on_sig_child (gint sig_num) { gint pid; @@ -492,6 +473,5 @@ on_sig_child (gint sig_num) break; } } -#endif /* SIGCHLD */ #endif /* !G_OS_WIN32 */ diff --git a/libgimp/Makefile.am b/libgimp/Makefile.am index ec98cbc05b..2a08986375 100644 --- a/libgimp/Makefile.am +++ b/libgimp/Makefile.am @@ -47,6 +47,8 @@ libgimpi_a_SOURCES = \ gimpprotocol.h \ gimpquerybox.c \ gimpquerybox.h \ + gimpsignal.c \ + gimpsignal.h \ gimpsizeentry.c \ gimpsizeentry.h \ gimpunitmenu.c \ diff --git a/libgimp/gimp.c b/libgimp/gimp.c index d4a1581337..c3dc194a3c 100644 --- a/libgimp/gimp.c +++ b/libgimp/gimp.c @@ -20,9 +20,13 @@ #include #include -#include #include #include +#ifndef G_OS_WIN32 +#include "gimpsignal.h" +#else +#include +#endif #include #include #include @@ -73,17 +77,17 @@ void gimp_read_expect_msg (WireMessage *msg, gint type); #ifndef G_OS_WIN32 -static RETSIGTYPE gimp_signal (gint signum); +static void gimp_plugin_signalhandler (gint signum); #endif -static int gimp_write (GIOChannel *channel , guint8 *buf, gulong count); -static int gimp_flush (GIOChannel *channel); -static void gimp_loop (void); -static void gimp_config (GPConfig *config); -static void gimp_proc_run (GPProcRun *proc_run); -static void gimp_temp_proc_run (GPProcRun *proc_run); -static void gimp_message_func (gchar *str); -static void gimp_process_message (WireMessage *msg); -static void gimp_close (void); +static int gimp_write (GIOChannel *channel , guint8 *buf, gulong count); +static int gimp_flush (GIOChannel *channel); +static void gimp_loop (void); +static void gimp_config (GPConfig *config); +static void gimp_proc_run (GPProcRun *proc_run); +static void gimp_temp_proc_run (GPProcRun *proc_run); +static void gimp_message_func (gchar *str); +static void gimp_process_message (WireMessage *msg); +static void gimp_close (void); GIOChannel *_readchannel = NULL; @@ -193,26 +197,14 @@ gimp_main (int argc, * about the program error, and offer debugging if the plug-in * has been built with MSVC, and the user has MSVC installed. */ -#ifdef SIGHUP - signal (SIGHUP, gimp_signal); -#endif - signal (SIGINT, gimp_signal); -#ifdef SIGQUIT - signal (SIGQUIT, gimp_signal); -#endif -#ifdef SIGBUS - signal (SIGBUS, gimp_signal); -#endif -#ifdef SIGSEGV - signal (SIGSEGV, gimp_signal); -#endif -#ifdef SIGPIPE - signal (SIGPIPE, gimp_signal); -#endif - signal (SIGTERM, gimp_signal); -#ifdef SIGFPE - signal (SIGFPE, gimp_signal); -#endif + gimp_signal_syscallrestart (SIGHUP, gimp_plugin_signalhandler); + gimp_signal_syscallrestart (SIGINT, gimp_plugin_signalhandler); + gimp_signal_syscallrestart (SIGQUIT, gimp_plugin_signalhandler); + gimp_signal_syscallrestart (SIGBUS, gimp_plugin_signalhandler); + gimp_signal_syscallrestart (SIGSEGV, gimp_plugin_signalhandler); + gimp_signal_syscallrestart (SIGPIPE, gimp_plugin_signalhandler); + gimp_signal_syscallrestart (SIGTERM, gimp_plugin_signalhandler); + gimp_signal_syscallrestart (SIGFPE, gimp_plugin_signalhandler); #endif #ifndef G_OS_WIN32 @@ -1145,8 +1137,8 @@ gimp_request_wakeups (void) } #ifndef G_OS_WIN32 -static RETSIGTYPE -gimp_signal (gint signum) +static void +gimp_plugin_signalhandler (gint signum) { static gboolean caught_fatal_sig = FALSE; diff --git a/libgimp/gimpsignal.c b/libgimp/gimpsignal.c new file mode 100644 index 0000000000..745c565c2c --- /dev/null +++ b/libgimp/gimpsignal.c @@ -0,0 +1,72 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * $Revision$ + */ + +#include "gimpsignal.h" + +/** + * gimp_signal: + * @signum: selects signal to be handled see man 5 signal + * @handler: handler that maps to signum. Invoked by O/S. + * handler gets signal that caused invocation. + * @sa_flags: preferences. OR'ed SA_. See signal.h + * + * This function furnishes a workalike for signal(2) but + * which internally invokes sigaction(2) after certain + * sa_flags are set; these primarily to ensure restarting + * of interrupted system calls. See sigaction(2) It is a + * aid to transition and not new development: that effort + * should employ sigaction directly. [ 18.04.2000] + * + * Cause handler to be run when signum is delivered. We + * use sigaction(2) rather than signal(2) so that we can control the + * signal hander's environment completely via sa_flags: some signal(2) + * implementations differ in their sematics, so we need to nail down + * exactly what we want. [ 06.04.2000] + * + * Returns: RetSigType (a reference to a signal handling function) + * + */ + +/* Courtesy of Austin Donnelly 06-04-2000 to address bug #2742 */ + +RetSigType +gimp_signal_private (gint signum, void (*gimp_sighandler)(int), gint sa_flags) +{ + int ret; + struct sigaction sa; + struct sigaction osa; + + /* this field is a union of sa_sighandler.sa_sighandler1 and */ + /* sa_sigaction1 - don't set both at once... */ + + sa.sa_handler = gimp_sighandler; + + /* Mask all signals while handler runs to avoid re-entrancy + * problems. */ + sigfillset (&sa.sa_mask); + + sa.sa_flags = sa_flags; + + ret = sigaction (signum, &sa, &osa); + if (ret < 0) + gimp_fatal_error ("unable to set handler for signal %d\n", signum); + return osa.sa_handler; +} diff --git a/libgimp/gimpsignal.h b/libgimp/gimpsignal.h new file mode 100644 index 0000000000..0dd418b79c --- /dev/null +++ b/libgimp/gimpsignal.h @@ -0,0 +1,57 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * $Revision$ + */ + +#ifndef __GIMP_SIGNAL_H__ +#define __GIMP_SIGNAL_H__ + +/* A gimp-level interface to a Posix.1-compliant signal package lives here */ +/* For 1.2, this gimp-level interface mostly passes through to posix calls */ +/* without modification. Certain calls manipulate struct sigaction in */ +/* ways useful to Gimp. */ + +#include +#include + +/* RETSIGTYPE is a reference to a + * (signal handler) function that + * takes a signal ID and returns + * void. signal(2) returns such + * references; so does + * gimp_signal_private. + */ + +typedef void (*RetSigType)(gint); + +/* Internal implementation that can be */ +/* DEFINEd into various flavors of */ +/* signal(2) lookalikes. */ + +RetSigType gimp_signal_private (gint signum, void (*gimp_sighandler)(int), gint sa_flags); + +/* the gimp_signal_syscallrestart() */ +/* lookalike looks like signal(2) but */ +/* quietly requests the restarting of */ +/* system calls. Addresses #2742 */ + +# define gimp_signal_syscallrestart(x, y) gimp_signal_private ((x), (y), SA_RESTART) + +#endif /* __GIMP_SIGNAL_H__ */ + diff --git a/libgimpbase/gimpsignal.c b/libgimpbase/gimpsignal.c new file mode 100644 index 0000000000..745c565c2c --- /dev/null +++ b/libgimpbase/gimpsignal.c @@ -0,0 +1,72 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * $Revision$ + */ + +#include "gimpsignal.h" + +/** + * gimp_signal: + * @signum: selects signal to be handled see man 5 signal + * @handler: handler that maps to signum. Invoked by O/S. + * handler gets signal that caused invocation. + * @sa_flags: preferences. OR'ed SA_. See signal.h + * + * This function furnishes a workalike for signal(2) but + * which internally invokes sigaction(2) after certain + * sa_flags are set; these primarily to ensure restarting + * of interrupted system calls. See sigaction(2) It is a + * aid to transition and not new development: that effort + * should employ sigaction directly. [ 18.04.2000] + * + * Cause handler to be run when signum is delivered. We + * use sigaction(2) rather than signal(2) so that we can control the + * signal hander's environment completely via sa_flags: some signal(2) + * implementations differ in their sematics, so we need to nail down + * exactly what we want. [ 06.04.2000] + * + * Returns: RetSigType (a reference to a signal handling function) + * + */ + +/* Courtesy of Austin Donnelly 06-04-2000 to address bug #2742 */ + +RetSigType +gimp_signal_private (gint signum, void (*gimp_sighandler)(int), gint sa_flags) +{ + int ret; + struct sigaction sa; + struct sigaction osa; + + /* this field is a union of sa_sighandler.sa_sighandler1 and */ + /* sa_sigaction1 - don't set both at once... */ + + sa.sa_handler = gimp_sighandler; + + /* Mask all signals while handler runs to avoid re-entrancy + * problems. */ + sigfillset (&sa.sa_mask); + + sa.sa_flags = sa_flags; + + ret = sigaction (signum, &sa, &osa); + if (ret < 0) + gimp_fatal_error ("unable to set handler for signal %d\n", signum); + return osa.sa_handler; +} diff --git a/libgimpbase/gimpsignal.h b/libgimpbase/gimpsignal.h new file mode 100644 index 0000000000..0dd418b79c --- /dev/null +++ b/libgimpbase/gimpsignal.h @@ -0,0 +1,57 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * $Revision$ + */ + +#ifndef __GIMP_SIGNAL_H__ +#define __GIMP_SIGNAL_H__ + +/* A gimp-level interface to a Posix.1-compliant signal package lives here */ +/* For 1.2, this gimp-level interface mostly passes through to posix calls */ +/* without modification. Certain calls manipulate struct sigaction in */ +/* ways useful to Gimp. */ + +#include +#include + +/* RETSIGTYPE is a reference to a + * (signal handler) function that + * takes a signal ID and returns + * void. signal(2) returns such + * references; so does + * gimp_signal_private. + */ + +typedef void (*RetSigType)(gint); + +/* Internal implementation that can be */ +/* DEFINEd into various flavors of */ +/* signal(2) lookalikes. */ + +RetSigType gimp_signal_private (gint signum, void (*gimp_sighandler)(int), gint sa_flags); + +/* the gimp_signal_syscallrestart() */ +/* lookalike looks like signal(2) but */ +/* quietly requests the restarting of */ +/* system calls. Addresses #2742 */ + +# define gimp_signal_syscallrestart(x, y) gimp_signal_private ((x), (y), SA_RESTART) + +#endif /* __GIMP_SIGNAL_H__ */ +