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