Change to the linux kernel coding style
[wmaker-crm.git] / src / monitor.c
1 /* monitor.c - monitors the wmaker process
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 1997-2004 Alfredo K. Kojima
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
21 */
22
23 #include "wconfig.h"
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <time.h>
27 #include <signal.h>
28 #include <sys/wait.h>
29 #ifdef __FreeBSD__
30 #include <sys/signal.h>
31 #endif
32
33 #include <X11/Xlib.h>
34 #include <X11/Xutil.h>
35 #include <X11/Xproto.h>
36
37 #include "WindowMaker.h"
38 #include "screen.h"
39 #include "window.h"
40 #include "dialog.h"
41 #include "funcs.h"
42
43 /****** Global Variables ******/
44
45 extern WPreferences wPreferences;
46
47 extern int wScreenCount;
48
49 int showCrashDialog(int sig)
50 {
51 int crashAction;
52
53 dpy = XOpenDisplay(NULL);
54 if (dpy) {
55 /* XXX TODO make sure that window states are saved and restored via netwm */
56
57 XGrabServer(dpy);
58 crashAction = wShowCrashingDialogPanel(sig);
59 XCloseDisplay(dpy);
60 dpy = NULL;
61 } else {
62 wsyserror(_("cannot open connection for crashing dialog panel. Aborting."));
63 crashAction = WMAbort;
64 }
65
66 if (crashAction == WMStartAlternate) {
67 int i;
68
69 wmessage(_("trying to start alternate window manager..."));
70
71 for (i = 0; i < WMGetArrayItemCount(wPreferences.fallbackWMs); i++) {
72 Restart(WMGetFromArray(wPreferences.fallbackWMs, i), False);
73 }
74
75 wfatal(_("failed to start alternate window manager. Aborting."));
76
77 return 0;
78 } else if (crashAction == WMAbort)
79 return 0;
80 else
81 return 1;
82 }
83
84 int MonitorLoop(int argc, char **argv)
85 {
86 pid_t pid, exited;
87 char **child_argv = wmalloc(sizeof(char *) * (argc + 2));
88 int i, status;
89 time_t last_start;
90 Bool error = False;
91
92 for (i = 0; i < argc; i++)
93 child_argv[i] = argv[i];
94 child_argv[i++] = "--for-real";
95 child_argv[i] = NULL;
96
97 for (;;) {
98 last_start = time(NULL);
99
100 /* Start Window Maker */
101 pid = fork();
102 if (pid == 0) {
103 execvp(child_argv[0], child_argv);
104 wsyserror(_("Error respawning Window Maker"));
105 exit(1);
106 } else if (pid < 0) {
107 wsyserror(_("Error respawning Window Maker"));
108 exit(1);
109 }
110
111 do {
112 if ((exited = waitpid(-1, &status, 0)) < 0) {
113 wsyserror(_("Error during monitoring of Window Maker process."));
114 error = True;
115 break;
116 }
117 } while (exited != pid);
118
119 if (error)
120 break;
121
122 child_argv[argc] = "--for-real-";
123
124 /* Check if the wmaker process exited due to a crash */
125 if (WIFSIGNALED(status) &&
126 (WTERMSIG(status) == SIGSEGV ||
127 WTERMSIG(status) == SIGBUS ||
128 WTERMSIG(status) == SIGILL || WTERMSIG(status) == SIGABRT || WTERMSIG(status) == SIGFPE)) {
129 /* If so, we check when was the last restart.
130 * If it was less than 3s ago, it's a bad sign, so we show
131 * the crash panel and ask the user what to do */
132 if (time(NULL) - last_start < 3) {
133 if (showCrashDialog(WTERMSIG(status)) == 0) {
134 return 1;
135 }
136 }
137 wwarning(_("Window Maker exited due to a crash (signal %i) and will be restarted."),
138 WTERMSIG(status));
139 } else
140 break;
141 }
142 return 0;
143 }