summaryrefslogtreecommitdiff
path: root/sal/osl/unx/signal.c
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2000-09-18 14:18:43 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2000-09-18 14:18:43 +0000
commit9399c662f36c385b0c705eb34e636a9aec450282 (patch)
treef502e9d9258960ff214ab90e98e31d0075e60196 /sal/osl/unx/signal.c
initial import
Diffstat (limited to 'sal/osl/unx/signal.c')
-rw-r--r--sal/osl/unx/signal.c490
1 files changed, 490 insertions, 0 deletions
diff --git a/sal/osl/unx/signal.c b/sal/osl/unx/signal.c
new file mode 100644
index 000000000000..19a6de1f092f
--- /dev/null
+++ b/sal/osl/unx/signal.c
@@ -0,0 +1,490 @@
+/*************************************************************************
+ *
+ * $RCSfile: signal.c,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 15:17:21 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+
+/* system headers */
+#include "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+#include <osl/signal.h>
+#include <osl/process.h>
+
+
+#define ACT_IGNORE 1
+#define ACT_ABORT 2
+#define ACT_EXIT 3
+#define ACT_SYSTEM 4
+#define ACT_HIDE 5
+
+typedef struct _oslSignalHandlerImpl
+{
+ oslSignalHandlerFunction Handler;
+ void* pData;
+ struct _oslSignalHandlerImpl* pNext;
+} oslSignalHandlerImpl;
+
+static struct SignalAction
+{
+ int Signal;
+ int Action;
+ void (*Handler)(int);
+} Signals[] =
+{
+ { SIGHUP, ACT_IGNORE, NULL }, /* hangup */
+ { SIGINT, ACT_EXIT, NULL }, /* interrupt (rubout) */
+ { SIGQUIT, ACT_ABORT, NULL }, /* quit (ASCII FS) */
+ { SIGILL, ACT_ABORT, NULL }, /* illegal instruction (not reset when caught) */
+ { SIGTRAP, ACT_ABORT, NULL }, /* trace trap (not reset when caught) */
+#if ( SIGIOT != SIGABRT )
+ { SIGIOT, ACT_ABORT, NULL }, /* IOT instruction */
+#endif
+ { SIGABRT, ACT_ABORT, NULL }, /* used by abort, replace SIGIOT in the future */
+#ifdef SIGEMT
+ { SIGEMT, ACT_ABORT, NULL }, /* EMT instruction */
+#endif
+ { SIGFPE, ACT_ABORT, NULL }, /* floating point exception */
+ { SIGKILL, ACT_SYSTEM, NULL }, /* kill (cannot be caught or ignored) */
+ { SIGBUS, ACT_ABORT, NULL }, /* bus error */
+ { SIGSEGV, ACT_ABORT, NULL }, /* segmentation violation */
+#ifdef SIGSYS
+ { SIGSYS, ACT_ABORT, NULL }, /* bad argument to system call */
+#endif
+ { SIGPIPE, ACT_HIDE, NULL }, /* write on a pipe with no one to read it */
+ { SIGALRM, ACT_EXIT, NULL }, /* alarm clock */
+ { SIGTERM, ACT_EXIT, NULL }, /* software termination signal from kill */
+ { SIGUSR1, ACT_SYSTEM, NULL }, /* user defined signal 1 */
+ { SIGUSR2, ACT_SYSTEM, NULL }, /* user defined signal 2 */
+ { SIGCHLD, ACT_SYSTEM, NULL }, /* child status change */
+#ifdef SIGPWR
+ { SIGPWR, ACT_IGNORE, NULL }, /* power-fail restart */
+#endif
+ { SIGWINCH, ACT_IGNORE, NULL }, /* window size change */
+ { SIGURG, ACT_EXIT, NULL }, /* urgent socket condition */
+#ifdef SIGPOLL
+ { SIGPOLL, ACT_EXIT, NULL }, /* pollable event occured */
+#endif
+ { SIGSTOP, ACT_SYSTEM, NULL }, /* stop (cannot be caught or ignored) */
+ { SIGTSTP, ACT_SYSTEM, NULL }, /* user stop requested from tty */
+ { SIGCONT, ACT_SYSTEM, NULL }, /* stopped process has been continued */
+ { SIGTTIN, ACT_SYSTEM, NULL }, /* background tty read attempted */
+ { SIGTTOU, ACT_SYSTEM, NULL }, /* background tty write attempted */
+ { SIGVTALRM, ACT_EXIT, NULL }, /* virtual timer expired */
+ { SIGPROF, ACT_EXIT, NULL }, /* profiling timer expired */
+ { SIGXCPU, ACT_ABORT, NULL }, /* exceeded cpu limit */
+ { SIGXFSZ, ACT_ABORT, NULL } /* exceeded file size limit */
+};
+const int NoSignals = sizeof(Signals) / sizeof(struct SignalAction);
+
+static sal_Bool bInitSignal = sal_False;
+static oslMutex SignalListMutex;
+static oslSignalHandlerImpl* SignalList;
+static sal_Bool bDoHardKill = sal_False;
+static sal_Bool bDoNotUseSEGV = sal_False;
+
+static void SignalHandlerFunction(int);
+extern oslProcessError SAL_CALL osl_psz_getExecutableFile(sal_Char* pszBuffer, sal_uInt32 Max);
+oslProcessError SAL_CALL osl_getCommandArgs(sal_Char* pszBuffer, sal_uInt32 Max);
+
+static sal_Bool InitSignal()
+{
+ int i;
+ struct sigaction act;
+ struct sigaction oact;
+
+ /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+ char ProgFile[512];
+
+ if ((osl_psz_getExecutableFile(ProgFile, sizeof(ProgFile)) == osl_Process_E_None) &&
+ (strstr(ProgFile, "soffice") != NULL))
+ {
+ char CmdLine[512];
+
+ if ((osl_getCommandArgs(CmdLine, sizeof(CmdLine)) == osl_Process_E_None) &&
+ (strstr(CmdLine, "-bean") != NULL))
+ bDoHardKill = sal_True;
+ }
+
+ if ((osl_psz_getExecutableFile(ProgFile, sizeof(ProgFile)) == osl_Process_E_None) &&
+ (strstr(ProgFile, "stomcatd") != NULL))
+ {
+ bDoNotUseSEGV = sal_True;
+ }
+
+ /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+
+
+ SignalListMutex = osl_createMutex();
+
+ act.sa_handler = SignalHandlerFunction;
+ act.sa_flags = SA_RESTART;
+
+ sigfillset(&(act.sa_mask));
+
+ /* Initialize the rest of the signals */
+ for (i = 0; i < NoSignals; i++)
+ {
+ /* hack: stomcatd is attaching JavaVM wich dont work with an sigaction(SEGV) */
+ if (!bDoNotUseSEGV || (Signals[i].Signal != SIGSEGV))
+ {
+ if (Signals[i].Action != ACT_SYSTEM)
+ {
+ if (Signals[i].Action == ACT_HIDE)
+ {
+ struct sigaction ign;
+
+ ign.sa_handler = SIG_IGN;
+ ign.sa_flags = 0;
+
+ if (sigaction(Signals[i].Signal, &ign, &oact) == 0)
+ Signals[i].Handler = oact.sa_handler;
+ else
+ Signals[i].Handler = SIG_DFL;
+ }
+ else
+ if (sigaction(Signals[i].Signal, &act, &oact) == 0)
+ Signals[i].Handler = oact.sa_handler;
+ else
+ Signals[i].Handler = SIG_DFL;
+ }
+ }
+ }
+
+ return sal_True;
+}
+
+static sal_Bool DeInitSignal()
+{
+ int i;
+ struct sigaction act;
+
+ act.sa_flags = 0;
+ sigemptyset(&(act.sa_mask));
+
+ /* Initialize the rest of the signals */
+ for (i = NoSignals - 1; i >= 0; i--)
+ if (Signals[i].Action != ACT_SYSTEM)
+ {
+ act.sa_handler = Signals[i].Handler;
+
+ sigaction(Signals[i].Signal, &act, NULL);
+ }
+
+ osl_destroyMutex(SignalListMutex);
+
+ return sal_False;
+}
+
+static oslSignalAction CallSignalHandler(oslSignalInfo *pInfo)
+{
+ oslSignalHandlerImpl* pHandler = SignalList;
+ oslSignalAction Action = osl_Signal_ActCallNextHdl;
+
+ /* PORTAL EA SOFFICE TERMINATION HACK BEGIN */
+ struct sigaction act;
+ struct sigaction oldact;
+ int nRet=0;
+
+ act.sa_flags = 0;
+ sigemptyset(&(act.sa_mask));
+
+ act.sa_handler=SIG_DFL;
+ nRet = sigaction(SIGALRM,&act,&oldact);
+ if ( nRet < 0 )
+ {
+ OSL_TRACE("sigaction failed : '%s'\n",strerror(errno));
+ }
+
+ alarm(30);
+ /* PORTAL EA SOFFICE TERMINATION HACK END */
+
+ while (pHandler != NULL)
+ {
+ if ((Action = pHandler->Handler(pHandler->pData, pInfo))
+ != osl_Signal_ActCallNextHdl)
+ break;
+
+ pHandler = pHandler->pNext;
+ }
+
+ /* PORTAL EA SOFFICE TERMINATION HACK BEGIN */
+ alarm(0);
+ /* PORTAL EA SOFFICE TERMINATION HACK END */
+
+
+ return Action;
+}
+
+static void CallSystemHandler(int Signal)
+{
+ int i;
+ struct sigaction act;
+
+ for (i = 0; i < NoSignals; i++)
+ {
+ if (Signals[i].Signal == Signal)
+ break;
+ }
+
+ if (i < NoSignals)
+ {
+ if ((Signals[i].Handler == NULL) ||
+ (Signals[i].Handler == SIG_DFL) ||
+ (Signals[i].Handler == SIG_IGN) ||
+ (Signals[i].Handler == SIG_ERR))
+ {
+ switch (Signals[i].Action)
+ {
+ case ACT_EXIT: /* terminate */
+ exit(255);
+ break;
+
+ case ACT_ABORT: /* terminate witch core dump */
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigemptyset(&(act.sa_mask));
+ sigaction(SIGABRT, &act, NULL);
+ abort();
+ break;
+
+ case ACT_IGNORE: /* ignore */
+ break;
+
+ default: /* should never happen */
+ OSL_ASSERT(0);
+ }
+ }
+ else
+ (*Signals[i].Handler)(Signal);
+ }
+}
+
+/*****************************************************************************/
+/* SignalHandlerFunction */
+/*****************************************************************************/
+static void SignalHandlerFunction(int Signal)
+{
+ oslSignalInfo Info;
+ struct sigaction act;
+
+ Info.UserSignal = Signal;
+ Info.UserData = NULL;
+
+ switch (Signal)
+ {
+ case SIGBUS:
+ case SIGILL:
+ case SIGSEGV:
+ Info.Signal = osl_Signal_AccessViolation;
+ break;
+
+ case -1:
+ Info.Signal = osl_Signal_IntegerDivideByZero;
+ break;
+
+ case SIGFPE:
+ Info.Signal = osl_Signal_FloatDivideByZero;
+ break;
+
+ case SIGINT:
+ case SIGIOT:
+ case SIGTERM:
+ case SIGQUIT:
+ case SIGHUP:
+ Info.Signal = osl_Signal_Terminate;
+ break;
+
+ default:
+ Info.Signal = osl_Signal_System;
+ break;
+ }
+
+ /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+ if (bDoHardKill && (Info.Signal == osl_Signal_AccessViolation))
+ _exit(255);
+ /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+
+ switch (CallSignalHandler(&Info))
+ {
+ case osl_Signal_ActCallNextHdl:
+ CallSystemHandler(Signal);
+ break;
+
+ case osl_Signal_ActAbortApp:
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigemptyset(&(act.sa_mask));
+ sigaction(SIGABRT, &act, NULL);
+ abort();
+ break;
+
+ case osl_Signal_ActKillApp:
+ exit(255);
+ break;
+ default:
+ break;
+ }
+}
+
+/*****************************************************************************/
+/* osl_addSignalHandler */
+/*****************************************************************************/
+oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction Handler, void* pData)
+{
+ oslSignalHandlerImpl* pHandler;
+
+ OSL_ASSERT(Handler != NULL);
+ if ( Handler == 0 )
+ {
+ return 0;
+ }
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ pHandler = (oslSignalHandlerImpl*) calloc(1, sizeof(oslSignalHandlerImpl));
+
+ if (pHandler != NULL)
+ {
+ pHandler->Handler = Handler;
+ pHandler->pData = pData;
+
+ osl_acquireMutex(SignalListMutex);
+
+ pHandler->pNext = SignalList;
+ SignalList = pHandler;
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (pHandler);
+ }
+
+ return (NULL);
+}
+
+/*****************************************************************************/
+/* osl_removeSignalHandler */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler Handler)
+{
+ oslSignalHandlerImpl *pHandler, *pPrevious = NULL;
+
+ OSL_ASSERT(Handler != NULL);
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ osl_acquireMutex(SignalListMutex);
+
+ pHandler = SignalList;
+
+ while (pHandler != NULL)
+ {
+ if (pHandler == Handler)
+ {
+ if (pPrevious)
+ pPrevious->pNext = pHandler->pNext;
+ else
+ SignalList = pHandler->pNext;
+
+ osl_releaseMutex(SignalListMutex);
+
+ if (SignalList == NULL)
+ bInitSignal = DeInitSignal();
+
+ free(pHandler);
+
+ return (sal_True);
+ }
+
+ pPrevious = pHandler;
+ pHandler = pHandler->pNext;
+ }
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (sal_False);
+}
+
+/*****************************************************************************/
+/* osl_raiseSignal */
+/*****************************************************************************/
+oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 UserSignal, void* UserData)
+{
+ oslSignalInfo Info;
+ oslSignalAction Action;
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ osl_acquireMutex(SignalListMutex);
+
+ Info.Signal = osl_Signal_User;
+ Info.UserSignal = UserSignal;
+ Info.UserData = UserData;
+
+ Action = CallSignalHandler(&Info);
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (Action);
+}
+