Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /*********************************************************** |
2 | ||
3 | Copyright 1987, 1998 The Open Group | |
4 | ||
5 | Permission to use, copy, modify, distribute, and sell this software and its | |
6 | documentation for any purpose is hereby granted without fee, provided that | |
7 | the above copyright notice appear in all copies and that both that | |
8 | copyright notice and this permission notice appear in supporting | |
9 | documentation. | |
10 | ||
11 | The above copyright notice and this permission notice shall be included in | |
12 | all copies or substantial portions of the Software. | |
13 | ||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |
18 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
20 | ||
21 | Except as contained in this notice, the name of The Open Group shall not be | |
22 | used in advertising or otherwise to promote the sale, use or other dealings | |
23 | in this Software without prior written authorization from The Open Group. | |
24 | ||
25 | Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. | |
26 | ||
27 | All Rights Reserved | |
28 | ||
29 | Permission to use, copy, modify, and distribute this software and its | |
30 | documentation for any purpose and without fee is hereby granted, | |
31 | provided that the above copyright notice appear in all copies and that | |
32 | both that copyright notice and this permission notice appear in | |
33 | supporting documentation, and that the name of Digital not be | |
34 | used in advertising or publicity pertaining to distribution of the | |
35 | software without specific, written prior permission. | |
36 | ||
37 | DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | |
38 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |
39 | DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | |
40 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
41 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
42 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
43 | SOFTWARE. | |
44 | ||
45 | ******************************************************************/ | |
46 | ||
47 | #ifdef HAVE_DIX_CONFIG_H | |
48 | #include <dix-config.h> | |
49 | #endif | |
50 | ||
51 | #include <stdio.h> | |
52 | #include <X11/X.h> | |
53 | #include "os.h" | |
54 | #include "osdep.h" | |
55 | #include <X11/Xos.h> | |
56 | #include <signal.h> | |
57 | #include <errno.h> | |
58 | #ifdef HAVE_DLFCN_H | |
59 | #include <dlfcn.h> | |
60 | #endif | |
61 | #ifdef HAVE_BACKTRACE | |
62 | #include <execinfo.h> | |
63 | #endif | |
64 | ||
65 | #include "misc.h" | |
66 | ||
67 | #include "dixstruct.h" | |
68 | ||
69 | #if !defined(SYSV) && !defined(WIN32) | |
70 | #include <sys/resource.h> | |
71 | #endif | |
72 | ||
73 | #ifndef ADMPATH | |
74 | #define ADMPATH "/usr/adm/X%smsgs" | |
75 | #endif | |
76 | ||
77 | extern char *display; | |
78 | ||
79 | #ifdef RLIMIT_DATA | |
80 | int limitDataSpace = -1; | |
81 | #endif | |
82 | #ifdef RLIMIT_STACK | |
83 | int limitStackSpace = -1; | |
84 | #endif | |
85 | #ifdef RLIMIT_NOFILE | |
86 | int limitNoFile = -1; | |
87 | #endif | |
88 | ||
89 | static OsSigWrapperPtr OsSigWrapper = NULL; | |
90 | ||
91 | OsSigWrapperPtr | |
92 | OsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper) | |
93 | { | |
94 | OsSigWrapperPtr oldSigWrapper = OsSigWrapper; | |
95 | ||
96 | OsSigWrapper = newSigWrapper; | |
97 | ||
98 | return oldSigWrapper; | |
99 | } | |
100 | ||
101 | /* | |
102 | * OsSigHandler -- | |
103 | * Catch unexpected signals and exit or continue cleanly. | |
104 | */ | |
105 | #if !defined(WIN32) || defined(__CYGWIN__) | |
106 | static void | |
107 | #ifdef SA_SIGINFO | |
108 | OsSigHandler(int signo, siginfo_t * sip, void *unused) | |
109 | #else | |
110 | OsSigHandler(int signo) | |
111 | #endif | |
112 | { | |
113 | #ifdef RTLD_DI_SETSIGNAL | |
114 | const char *dlerr = dlerror(); | |
115 | ||
116 | if (dlerr) { | |
117 | LogMessageVerbSigSafe(X_ERROR, 1, "Dynamic loader error: %s\n", dlerr); | |
118 | } | |
119 | #endif /* RTLD_DI_SETSIGNAL */ | |
120 | ||
121 | if (OsSigWrapper != NULL) { | |
122 | if (OsSigWrapper(signo) == 0) { | |
123 | /* ddx handled signal and wants us to continue */ | |
124 | return; | |
125 | } | |
126 | } | |
127 | ||
128 | /* log, cleanup, and abort */ | |
129 | xorg_backtrace(); | |
130 | ||
131 | #ifdef SA_SIGINFO | |
132 | if (sip->si_code == SI_USER) { | |
133 | ErrorFSigSafe("Received signal %u sent by process %u, uid %u\n", signo, | |
134 | sip->si_pid, sip->si_uid); | |
135 | } | |
136 | else { | |
137 | switch (signo) { | |
138 | case SIGSEGV: | |
139 | case SIGBUS: | |
140 | case SIGILL: | |
141 | case SIGFPE: | |
142 | ErrorFSigSafe("%s at address %p\n", strsignal(signo), sip->si_addr); | |
143 | } | |
144 | } | |
145 | #endif | |
146 | ||
147 | FatalError("Caught signal %d (%s). Server aborting\n", | |
148 | signo, strsignal(signo)); | |
149 | } | |
150 | #endif /* !WIN32 || __CYGWIN__ */ | |
151 | ||
152 | #include "busfault.h" | |
153 | ||
154 | void | |
155 | OsInit(void) | |
156 | { | |
157 | static Bool been_here = FALSE; | |
158 | static const char *devnull = "/dev/null"; | |
159 | char fname[PATH_MAX]; | |
160 | ||
161 | if (!been_here) { | |
162 | #if !defined(WIN32) || defined(__CYGWIN__) | |
163 | struct sigaction act, oact; | |
164 | int i; | |
165 | ||
166 | int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, | |
167 | SIGSYS, | |
168 | SIGXCPU, | |
169 | SIGXFSZ, | |
170 | #ifdef SIGEMT | |
171 | SIGEMT, | |
172 | #endif | |
173 | 0 /* must be last */ | |
174 | }; | |
175 | sigemptyset(&act.sa_mask); | |
176 | #ifdef SA_SIGINFO | |
177 | act.sa_sigaction = OsSigHandler; | |
178 | act.sa_flags = SA_SIGINFO; | |
179 | #else | |
180 | act.sa_handler = OsSigHandler; | |
181 | act.sa_flags = 0; | |
182 | #endif | |
183 | for (i = 0; siglist[i] != 0; i++) { | |
184 | if (sigaction(siglist[i], &act, &oact)) { | |
185 | ErrorF("failed to install signal handler for signal %d: %s\n", | |
186 | siglist[i], strerror(errno)); | |
187 | } | |
188 | } | |
189 | #endif /* !WIN32 || __CYGWIN__ */ | |
190 | #ifdef BUSFAULT | |
191 | busfault_init(); | |
192 | #endif | |
193 | ||
194 | #ifdef HAVE_BACKTRACE | |
195 | /* | |
196 | * initialize the backtracer, since the ctor calls dlopen(), which | |
197 | * calls malloc(), which isn't signal-safe. | |
198 | */ | |
199 | do { | |
200 | void *array; | |
201 | ||
202 | backtrace(&array, 1); | |
203 | } while (0); | |
204 | #endif | |
205 | ||
206 | #ifdef RTLD_DI_SETSIGNAL | |
207 | /* Tell runtime linker to send a signal we can catch instead of SIGKILL | |
208 | * for failures to load libraries/modules at runtime so we can clean up | |
209 | * after ourselves. | |
210 | */ | |
211 | int failure_signal = SIGQUIT; | |
212 | ||
213 | dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal); | |
214 | #endif | |
215 | ||
216 | #if !defined(XQUARTZ) /* STDIN is already /dev/null and STDOUT/STDERR is managed by console_redirect.c */ | |
217 | # if defined(__APPLE__) | |
218 | int devnullfd = open(devnull, O_RDWR, 0); | |
219 | assert(devnullfd > 2); | |
220 | ||
221 | dup2(devnullfd, STDIN_FILENO); | |
222 | dup2(devnullfd, STDOUT_FILENO); | |
223 | close(devnullfd); | |
224 | # elif !defined(__CYGWIN__) | |
225 | fclose(stdin); | |
226 | fclose(stdout); | |
227 | # endif | |
228 | /* | |
229 | * If a write of zero bytes to stderr returns non-zero, i.e. -1, | |
230 | * then writing to stderr failed, and we'll write somewhere else | |
231 | * instead. (Apparently this never happens in the Real World.) | |
232 | */ | |
233 | if (write(2, fname, 0) == -1) { | |
234 | FILE *err; | |
235 | ||
236 | if (strlen(display) + strlen(ADMPATH) + 1 < sizeof fname) | |
237 | snprintf(fname, sizeof(fname), ADMPATH, display); | |
238 | else | |
239 | strcpy(fname, devnull); | |
240 | /* | |
241 | * uses stdio to avoid os dependencies here, | |
242 | * a real os would use | |
243 | * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) | |
244 | */ | |
245 | if (!(err = fopen(fname, "a+"))) | |
246 | err = fopen(devnull, "w"); | |
247 | if (err && (fileno(err) != 2)) { | |
248 | dup2(fileno(err), 2); | |
249 | fclose(err); | |
250 | } | |
251 | #if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__) | |
252 | { | |
253 | static char buf[BUFSIZ]; | |
254 | ||
255 | setvbuf(stderr, buf, _IOLBF, BUFSIZ); | |
256 | } | |
257 | #else | |
258 | setlinebuf(stderr); | |
259 | #endif | |
260 | } | |
261 | #endif /* !XQUARTZ */ | |
262 | ||
263 | #if !defined(WIN32) || defined(__CYGWIN__) | |
264 | if (getpgrp() == 0) | |
265 | setpgid(0, 0); | |
266 | #endif | |
267 | ||
268 | #ifdef RLIMIT_DATA | |
269 | if (limitDataSpace >= 0) { | |
270 | struct rlimit rlim; | |
271 | ||
272 | if (!getrlimit(RLIMIT_DATA, &rlim)) { | |
273 | if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max)) | |
274 | rlim.rlim_cur = limitDataSpace; | |
275 | else | |
276 | rlim.rlim_cur = rlim.rlim_max; | |
277 | (void) setrlimit(RLIMIT_DATA, &rlim); | |
278 | } | |
279 | } | |
280 | #endif | |
281 | #ifdef RLIMIT_STACK | |
282 | if (limitStackSpace >= 0) { | |
283 | struct rlimit rlim; | |
284 | ||
285 | if (!getrlimit(RLIMIT_STACK, &rlim)) { | |
286 | if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max)) | |
287 | rlim.rlim_cur = limitStackSpace; | |
288 | else | |
289 | rlim.rlim_cur = rlim.rlim_max; | |
290 | (void) setrlimit(RLIMIT_STACK, &rlim); | |
291 | } | |
292 | } | |
293 | #endif | |
294 | #ifdef RLIMIT_NOFILE | |
295 | if (limitNoFile >= 0) { | |
296 | struct rlimit rlim; | |
297 | ||
298 | if (!getrlimit(RLIMIT_NOFILE, &rlim)) { | |
299 | if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max)) | |
300 | rlim.rlim_cur = limitNoFile; | |
301 | else | |
302 | rlim.rlim_cur = rlim.rlim_max; | |
303 | (void) setrlimit(RLIMIT_NOFILE, &rlim); | |
304 | } | |
305 | } | |
306 | #endif | |
307 | LockServer(); | |
308 | been_here = TRUE; | |
309 | } | |
310 | TimerInit(); | |
311 | OsVendorInit(); | |
312 | OsResetSignals(); | |
313 | /* | |
314 | * No log file by default. OsVendorInit() should call LogInit() with the | |
315 | * log file name if logging to a file is desired. | |
316 | */ | |
317 | LogInit(NULL, NULL); | |
318 | SmartScheduleInit(); | |
319 | } | |
320 | ||
321 | void | |
322 | OsCleanup(Bool terminating) | |
323 | { | |
324 | if (terminating) { | |
325 | UnlockServer(); | |
326 | } | |
327 | } |