1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 20:38:08 +01:00

fixed some signal handling bugs

This commit is contained in:
kojima
2001-03-14 02:54:54 +00:00
parent b85df20ba2
commit 51b1bf34b9
11 changed files with 192 additions and 108 deletions

View File

@@ -7,6 +7,10 @@ Changes since version 0.64.0:
- added WINDOWS_MENU submenu type for root menu (Bastien Nocera <hadess@hadess.net>) - added WINDOWS_MENU submenu type for root menu (Bastien Nocera <hadess@hadess.net>)
- added kbd shortcuts for icon chooser - added kbd shortcuts for icon chooser
- use Hermes in wrlib - use Hermes in wrlib
- removed MOUSE_WS_WHEEL #defines
- fixed bug with multibyte text on libc5 systems (Osamu Ajiki <osam-a@astroarts.co.jp>)
- fixed race conditions on signal handlers
- SIGINT will gently exit, SIGTERM will not be handled
Changes since version 0.63.1: Changes since version 0.63.1:
............................. .............................

View File

@@ -4,6 +4,7 @@ Changes since wmaker 0.64.0:
- made programmatic scroller changes send notifications - made programmatic scroller changes send notifications
- replaced WMSetBoxExpandsToParent with WMSetViewExpands... - replaced WMSetBoxExpandsToParent with WMSetViewExpands...
- added WMGetLabelFont() - added WMGetLabelFont()
- added WMAddEternalTimerHandler()
changes since wmaker 0.63.1: changes since wmaker 0.63.1:
............................ ............................

View File

@@ -604,7 +604,7 @@ char *WMGetApplicationName();
char *WMPathForResourceOfType(char *resource, char *ext); char *WMPathForResourceOfType(char *resource, char *ext);
WMScreen *WMOpenScreen(); WMScreen *WMOpenScreen(const char *display);
WMScreen *WMCreateScreenWithRContext(Display *display, int screen, WMScreen *WMCreateScreenWithRContext(Display *display, int screen,
RContext *context); RContext *context);
@@ -658,6 +658,9 @@ void WMMaskEvent(Display *dpy, long mask, XEvent *event);
WMHandlerID WMAddTimerHandler(int milliseconds, WMCallback *callback, WMHandlerID WMAddTimerHandler(int milliseconds, WMCallback *callback,
void *cdata); void *cdata);
WMHandlerID WMAddEternalTimerHandler(int milliseconds, WMCallback *callback,
void *cdata);
void WMDeleteTimerWithClientData(void *cdata); void WMDeleteTimerWithClientData(void *cdata);
void WMDeleteTimerHandler(WMHandlerID handlerID); void WMDeleteTimerHandler(WMHandlerID handlerID);

View File

@@ -528,9 +528,9 @@ void W_HandleSelectionEvent(XEvent *event);
void W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event); void W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event);
void W_FlushASAPNotificationQueue(); void W_FlushASAPNotificationQueue(void);
void W_FlushIdleNotificationQueue(); void W_FlushIdleNotificationQueue(void);
struct W_Balloon *W_CreateBalloon(WMScreen *scr); struct W_Balloon *W_CreateBalloon(WMScreen *scr);

View File

@@ -38,6 +38,7 @@ typedef struct TimerHandler {
struct timeval when; /* when to call the callback */ struct timeval when; /* when to call the callback */
void *clientData; void *clientData;
struct TimerHandler *next; struct TimerHandler *next;
Bool permanent;
} TimerHandler; } TimerHandler;
@@ -125,6 +126,9 @@ rightNow(struct timeval *tv) {
(((t1).tv_sec == (t2).tv_sec) \ (((t1).tv_sec == (t2).tv_sec) \
&& ((t1).tv_usec > (t2).tv_usec))) && ((t1).tv_usec > (t2).tv_usec)))
#define IS_ZERO(tv) (tv.tv_sec == 0 && tv.tv_usec == 0)
#define SET_ZERO(tv) tv.tv_sec = 0, tv.tv_usec = 0
static void static void
addmillisecs(struct timeval *tv, int milliseconds) addmillisecs(struct timeval *tv, int milliseconds)
@@ -136,19 +140,11 @@ addmillisecs(struct timeval *tv, int milliseconds)
} }
WMHandlerID static void
WMAddTimerHandler(int milliseconds, WMCallback *callback, void *cdata) enqueueTimerHandler(TimerHandler *handler)
{ {
TimerHandler *handler, *tmp; TimerHandler *tmp;
handler = malloc(sizeof(TimerHandler));
if (!handler)
return NULL;
rightNow(&handler->when);
addmillisecs(&handler->when, milliseconds);
handler->callback = callback;
handler->clientData = cdata;
/* insert callback in queue, sorted by time left */ /* insert callback in queue, sorted by time left */
if (!timerHandler || !IS_AFTER(handler->when, timerHandler->when)) { if (!timerHandler || !IS_AFTER(handler->when, timerHandler->when)) {
/* first in the queue */ /* first in the queue */
@@ -162,6 +158,38 @@ WMAddTimerHandler(int milliseconds, WMCallback *callback, void *cdata)
handler->next = tmp->next; handler->next = tmp->next;
tmp->next = handler; tmp->next = handler;
} }
}
WMHandlerID
WMAddTimerHandler(int milliseconds, WMCallback *callback, void *cdata)
{
TimerHandler *handler;
handler = malloc(sizeof(TimerHandler));
if (!handler)
return NULL;
rightNow(&handler->when);
addmillisecs(&handler->when, milliseconds);
handler->callback = callback;
handler->clientData = cdata;
handler->permanent = False;
enqueueTimerHandler(handler);
return handler;
}
WMHandlerID
WMAddEternalTimerHandler(int milliseconds, WMCallback *callback, void *cdata)
{
TimerHandler *handler = WMAddTimerHandler(milliseconds, callback, cdata);
if (handler != NULL)
handler->permanent = True;
return handler; return handler;
} }
@@ -177,12 +205,18 @@ WMDeleteTimerWithClientData(void *cdata)
tmp = timerHandler; tmp = timerHandler;
if (tmp->clientData==cdata) { if (tmp->clientData==cdata) {
timerHandler = tmp->next; tmp->permanent = False;
wfree(tmp); if (!IS_ZERO(tmp->when)) {
timerHandler = tmp->next;
wfree(tmp);
}
} else { } else {
while (tmp->next) { while (tmp->next) {
if (tmp->next->clientData==cdata) { if (tmp->next->clientData==cdata) {
handler = tmp->next; handler = tmp->next;
handler->permanent = False;
if (IS_ZERO(handler->when))
break;
tmp->next = handler->next; tmp->next = handler->next;
wfree(handler); wfree(handler);
break; break;
@@ -203,6 +237,12 @@ WMDeleteTimerHandler(WMHandlerID handlerID)
return; return;
tmp = timerHandler; tmp = timerHandler;
handler->permanent = False;
if (IS_ZERO(handler->when))
return;
if (tmp==handler) { if (tmp==handler) {
timerHandler = handler->next; timerHandler = handler->next;
wfree(handler); wfree(handler);
@@ -241,7 +281,6 @@ WMAddIdleHandler(WMCallback *callback, void *cdata)
} }
void void
WMDeleteIdleHandler(WMHandlerID handlerID) WMDeleteIdleHandler(WMHandlerID handlerID)
{ {
@@ -306,6 +345,7 @@ checkIdleHandlers()
WMBag *handlerCopy; WMBag *handlerCopy;
WMBagIterator iter; WMBagIterator iter;
if (!idleHandler || WMGetBagItemCount(idleHandler)==0) { if (!idleHandler || WMGetBagItemCount(idleHandler)==0) {
W_FlushIdleNotificationQueue(); W_FlushIdleNotificationQueue();
/* make sure an observer in queue didn't added an idle handler */ /* make sure an observer in queue didn't added an idle handler */
@@ -349,12 +389,24 @@ checkTimerHandlers()
rightNow(&now); rightNow(&now);
while (timerHandler && IS_AFTER(now, timerHandler->when)) { handler = timerHandler;
while (handler && IS_AFTER(now, handler->when)) {
SET_ZERO(handler->when);
(*handler->callback)(handler->clientData);
handler = handler->next;
}
while (timerHandler && IS_ZERO(handler->when)) {
handler = timerHandler; handler = timerHandler;
timerHandler = timerHandler->next; timerHandler = timerHandler->next;
handler->next = NULL;
(*handler->callback)(handler->clientData); if (handler->permanent) {
wfree(handler); rightNow(&handler->when);
addmillisecs(&handler->when, milliseconds);
enqueueTimerHandler(handler);
} else {
wfree(handler);
}
} }
W_FlushASAPNotificationQueue(); W_FlushASAPNotificationQueue();
@@ -932,7 +984,7 @@ WMNextEvent(Display *dpy, XEvent *event)
while (XPending(dpy) == 0) { while (XPending(dpy) == 0) {
/* Do idle stuff */ /* Do idle stuff */
/* Do idle and timer stuff while there are no timer or X events */ /* Do idle and timer stuff while there are no timer or X events */
while (!XPending(dpy) && checkIdleHandlers()) { while (XPending(dpy) == 0 && checkIdleHandlers()) {
/* dispatch timer events */ /* dispatch timer events */
checkTimerHandlers(); checkTimerHandlers();
} }
@@ -942,7 +994,7 @@ WMNextEvent(Display *dpy, XEvent *event)
* timer/idle stuff. Or we might block forever waiting for * timer/idle stuff. Or we might block forever waiting for
* an event that already arrived. * an event that already arrived.
*/ */
/* wait to something happen */ /* wait for something to happen or a timer to expire */
W_WaitForEvent(dpy, 0); W_WaitForEvent(dpy, 0);
/* Check any expired timers */ /* Check any expired timers */

View File

@@ -42,9 +42,10 @@ generalize_xlfd (const char *xlfd)
char *slant = xlfd_get_element(xlfd, 4); char *slant = xlfd_get_element(xlfd, 4);
char *pxlsz = xlfd_get_element(xlfd, 7); char *pxlsz = xlfd_get_element(xlfd, 7);
len = snprintf(NULL, 0, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*," #define Xstrlen(A) ((A)?strlen(A):0)
"-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*", len = Xstrlen(xlfd)+Xstrlen(weight)+Xstrlen(slant)+Xstrlen(pxlsz)*2+50;
xlfd, weight, slant, pxlsz, pxlsz); #undef Xstrlen
buf = wmalloc(len + 1); buf = wmalloc(len + 1);
snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*," snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
"-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*", "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",

View File

@@ -516,13 +516,13 @@ loadPixmaps(WMScreen *scr)
WMScreen* WMScreen*
WMOpenScreen() WMOpenScreen(const char *display)
{ {
Display *dpy = XOpenDisplay(""); Display *dpy = XOpenDisplay(display);
if (!dpy) { if (!dpy) {
wwarning("WINGs: could not open display %s", wwarning("WINGs: could not open display %s",
XDisplayName("")); XDisplayName(display));
return NULL; return NULL;
} }

View File

@@ -247,10 +247,22 @@ typedef enum {
#define WCHECK_STATE(state) (state == WProgramState) #define WCHECK_STATE(state) (state == WProgramState)
#define WCHANGE_STATE(nstate) \
if (WProgramState == WSTATE_NORMAL\
|| nstate != WSTATE_MODAL)\ #define WCHANGE_STATE(nstate) {\
WProgramState = (nstate) if (WProgramState == WSTATE_NORMAL\
|| nstate != WSTATE_MODAL)\
WProgramState = (nstate); \
if (WProgramSigState != 0)\
WProgramState = WProgramSigState;\
}
/* only call inside signal handlers, with signals blocked */
#define SIG_WCHANGE_STATE(nstate) {\
WProgramSigState = (nstate);\
WProgramState = (nstate);\
}
/* notifications */ /* notifications */

View File

@@ -1062,8 +1062,7 @@ handleLogoPush(XEvent *event, void *data)
static char *msgs[] = { static char *msgs[] = {
"Have a nice day!", "Have a nice day!",
"Focus follow mouse users will burn in hell!!!", "Focus follow mouse users will burn in hell!!!",
"F'ck Canada!!!!", "Mooo Canada!!!!",
"F'ck Bastard Imperialists!!!",
"Hi! My name is bobby...", "Hi! My name is bobby...",
"AHH! The neurotic monkeys are after me!", "AHH! The neurotic monkeys are after me!",
"WHAT YOU SAY??", "WHAT YOU SAY??",

View File

@@ -138,9 +138,11 @@ int wXkbEventBase;
#endif #endif
/* special flags */ /* special flags */
char WProgramSigState = 0;
char WProgramState = WSTATE_NORMAL; char WProgramState = WSTATE_NORMAL;
char WDelayedActionSet = 0; char WDelayedActionSet = 0;
/* temporary stuff */ /* temporary stuff */
int wVisualID = -1; int wVisualID = -1;

View File

@@ -228,6 +228,8 @@ handleXIO(Display *xio_dpy)
static void static void
delayedAction(void *cdata) delayedAction(void *cdata)
{ {
if (WDelatedActionSet == 0)
return;
WDelayedActionSet = 0; WDelayedActionSet = 0;
/* /*
* Make the event dispatcher do whatever it needs to do, * Make the event dispatcher do whatever it needs to do,
@@ -238,6 +240,58 @@ delayedAction(void *cdata)
} }
/*
*----------------------------------------------------------------------
* handleExitSig--
* User generated exit signal handler.
*----------------------------------------------------------------------
*/
static RETSIGTYPE
handleExitSig(int sig)
{
sigset_t sigs;
sigfillset(&sigs);
sigprocmask(SIG_BLOCK, &sigs, NULL);
if (sig == SIGUSR1) {
#ifdef SYS_SIGLIST_DECLARED
wwarning(_("got signal %i (%s) - restarting\n"), sig, sys_siglist[sig]);
#else
wwarning(_("got signal %i - restarting\n"), sig);
#endif
SIG_WCHANGE_STATE(WSTATE_NEED_RESTART);
/* setup idle handler, so that this will be handled when
* the select() is returned becaused of the signal, even if
* there are no X events in the queue */
WDelayedActionSet = 1;
} else if (sig == SIGUSR2) {
#ifdef SYS_SIGLIST_DECLARED
wwarning(_("got signal %i (%s) - rereading defaults\n"), sig, sys_siglist[sig]);
#else
wwarning(_("got signal %i - rereading defaults\n"), sig);
#endif
SIG_WCHANGE_STATE(WSTATE_NEED_REREAD);
/* setup idle handler, so that this will be handled when
* the select() is returned becaused of the signal, even if
* there are no X events in the queue */
WDelayedActionSet = 1;
} else if (sig == SIGINT || sig == SIGHUP) {
#ifdef SYS_SIGLIST_DECLARED
wwarning(_("got signal %i (%s) - exiting...\n"), sig, sys_siglist[sig]);
#else
wwarning(_("got signal %i - exiting...\n"), sig);
#endif
SIG_WCHANGE_STATE(WSTATE_NEED_EXIT);
WDelayedActionSet = 1;
}
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
}
/* /*
*---------------------------------------------------------------------- *----------------------------------------------------------------------
@@ -262,53 +316,6 @@ handleSig(int sig)
* here. Xlib calls are not reentrant so the integrity of Xlib is * here. Xlib calls are not reentrant so the integrity of Xlib is
* not guaranteed if a Xlib call is made from a signal handler. * not guaranteed if a Xlib call is made from a signal handler.
*/ */
if (sig == SIGUSR1) {
#ifdef SYS_SIGLIST_DECLARED
wwarning(_("got signal %i (%s) - restarting\n"), sig, sys_siglist[sig]);
#else
wwarning(_("got signal %i - restarting\n"), sig);
#endif
WCHANGE_STATE(WSTATE_NEED_RESTART);
/* setup idle handler, so that this will be handled when
* the select() is returned becaused of the signal, even if
* there are no X events in the queue */
if (!WDelayedActionSet) {
WDelayedActionSet = 1;
WMAddIdleHandler(delayedAction, NULL);
}
return;
} else if (sig == SIGUSR2) {
#ifdef SYS_SIGLIST_DECLARED
wwarning(_("got signal %i (%s) - rereading defaults\n"), sig, sys_siglist[sig]);
#else
wwarning(_("got signal %i - rereading defaults\n"), sig);
#endif
WCHANGE_STATE(WSTATE_NEED_REREAD);
/* setup idle handler, so that this will be handled when
* the select() is returned becaused of the signal, even if
* there are no X events in the queue */
if (!WDelayedActionSet) {
WDelayedActionSet = 1;
WMAddIdleHandler(delayedAction, NULL);
}
return;
} else if (sig == SIGTERM || sig == SIGHUP) {
#ifdef SYS_SIGLIST_DECLARED
wwarning(_("got signal %i (%s) - exiting...\n"), sig, sys_siglist[sig]);
#else
wwarning(_("got signal %i - exiting...\n"), sig);
#endif
WCHANGE_STATE(WSTATE_NEED_EXIT);
if (!WDelayedActionSet) {
WDelayedActionSet = 1;
WMAddIdleHandler(delayedAction, NULL);
}
return;
}
#ifdef SYS_SIGLIST_DECLARED #ifdef SYS_SIGLIST_DECLARED
wfatal(_("got signal %i (%s)\n"), sig, sys_siglist[sig]); wfatal(_("got signal %i (%s)\n"), sig, sys_siglist[sig]);
@@ -333,6 +340,10 @@ handleSig(int sig)
dumpcore = 1; dumpcore = 1;
/*
* Yeah, we shouldn't do this, but it's already crashed anyway :P
*/
#ifndef NO_EMERGENCY_AUTORESTART #ifndef NO_EMERGENCY_AUTORESTART
/* Close the X connection and open a new one. This is to avoid messing /* Close the X connection and open a new one. This is to avoid messing
* Xlib because we call to Xlib functions in a signal handler. * Xlib because we call to Xlib functions in a signal handler.
@@ -384,18 +395,17 @@ handleSig(int sig)
} }
static RETSIGTYPE
ignoreSig(int signal)
{
return;
}
static RETSIGTYPE static RETSIGTYPE
buryChild(int foo) buryChild(int foo)
{ {
pid_t pid; pid_t pid;
int status; int status;
int save_errno = errno;
sigset_t sigs;
sigfillset(&sigs);
/* Block signals so that NotifyDeadProcess() doesn't get fux0red */
sigprocmask(SIG_BLOCK, &sigs, NULL);
/* R.I.P. */ /* R.I.P. */
/* If 2 or more kids exit in a small time window, before this handler gets /* If 2 or more kids exit in a small time window, before this handler gets
@@ -406,15 +416,13 @@ buryChild(int foo)
*/ */
while ((pid=waitpid(-1, &status, WNOHANG))>0 || (pid<0 && errno==EINTR)) { while ((pid=waitpid(-1, &status, WNOHANG))>0 || (pid<0 && errno==EINTR)) {
NotifyDeadProcess(pid, WEXITSTATUS(status)); NotifyDeadProcess(pid, WEXITSTATUS(status));
/*
* Make sure that the kid will be buried even if there are
* no events in the X event queue
*/
if (!WDelayedActionSet) {
WDelayedActionSet = 1;
WMAddIdleHandler(delayedAction, NULL);
}
} }
WDelayedActionSet = 1;
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
errno = save_errno;
} }
@@ -790,32 +798,34 @@ StartUp(Bool defaultScreenOnly)
wCursor[WCUR_TEXT] = XCreateFontCursor(dpy, XC_xterm); /* odd name???*/ wCursor[WCUR_TEXT] = XCreateFontCursor(dpy, XC_xterm); /* odd name???*/
wCursor[WCUR_SELECT] = XCreateFontCursor(dpy, XC_cross); wCursor[WCUR_SELECT] = XCreateFontCursor(dpy, XC_cross);
/* signal handler stuff that gets called when a signal is caught */
WMAddEternalTimerHandler(500, delayedAction, NULL);
/* emergency exit... */ /* emergency exit... */
sig_action.sa_handler = handleSig; sig_action.sa_handler = handleSig;
sigemptyset(&sig_action.sa_mask); sigemptyset(&sig_action.sa_mask);
/* Here we don't care about SA_RESTART since these signals will close sig_action.sa_flags = SA_RESTART;
* wmaker anyway.
* -Dan */
sig_action.sa_flags = 0;
sigaction(SIGINT, &sig_action, NULL);
sigaction(SIGTERM, &sig_action, NULL);
sigaction(SIGHUP, &sig_action, NULL);
sigaction(SIGQUIT, &sig_action, NULL); sigaction(SIGQUIT, &sig_action, NULL);
sigaction(SIGSEGV, &sig_action, NULL); sigaction(SIGSEGV, &sig_action, NULL);
sigaction(SIGBUS, &sig_action, NULL); sigaction(SIGBUS, &sig_action, NULL);
sigaction(SIGFPE, &sig_action, NULL); sigaction(SIGFPE, &sig_action, NULL);
sigaction(SIGABRT, &sig_action, NULL); sigaction(SIGABRT, &sig_action, NULL);
sig_action.sa_handler = handleExitSig;
/* Here we set SA_RESTART for safety, because SIGUSR1 may not be handled /* Here we set SA_RESTART for safety, because SIGUSR1 may not be handled
* immediately. * immediately.
* -Dan */ * -Dan */
sig_action.sa_flags = SA_RESTART; sig_action.sa_flags = SA_RESTART;
/* sigaction(SIGTERM, &sig_action, NULL);*/
sigaction(SIGINT, &sig_action, NULL);
sigaction(SIGHUP, &sig_action, NULL);
sigaction(SIGUSR1, &sig_action, NULL); sigaction(SIGUSR1, &sig_action, NULL);
sigaction(SIGUSR2, &sig_action, NULL); sigaction(SIGUSR2, &sig_action, NULL);
/* ignore dead pipe */ /* ignore dead pipe */
sig_action.sa_handler = ignoreSig; sig_action.sa_handler = SIG_IGN;
sig_action.sa_flags = SA_RESTART; sig_action.sa_flags = SA_RESTART;
sigaction(SIGPIPE, &sig_action, NULL); sigaction(SIGPIPE, &sig_action, NULL);