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