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 78#if !defined(SYSV) && !defined(WIN32) 79#include <sys/resource.h> 80#endif 81 82#ifndef ADMPATH 83#define ADMPATH "/usr/adm/X%smsgs" 84#endif 85 86extern char *display; 87#ifdef RLIMIT_DATA 88int limitDataSpace = -1; 89#endif 90#ifdef RLIMIT_STACK 91int limitStackSpace = -1; 92#endif 93#ifdef RLIMIT_NOFILE 94int limitNoFile = -1; 95#endif 96 97static OsSigWrapperPtr OsSigWrapper = NULL; 98 99OsSigWrapperPtr 100OsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper) 101{ 102 OsSigWrapperPtr oldSigWrapper = OsSigWrapper; 103 104 OsSigWrapper = newSigWrapper; 105 106 return oldSigWrapper; 107} 108 109/* 110 * OsSigHandler -- 111 * Catch unexpected signals and exit or continue cleanly. 112 */ 113static void 114#ifdef SA_SIGINFO 115OsSigHandler(int signo, siginfo_t *sip, void *unused) 116#else 117OsSigHandler(int signo) 118#endif 119{ 120#ifdef RTLD_DI_SETSIGNAL 121 const char *dlerr = dlerror(); 122 123 if (dlerr) { 124 LogMessage(X_ERROR, "Dynamic loader error: %s\n", dlerr); 125 } 126#endif /* RTLD_DI_SETSIGNAL */ 127 128 if (OsSigWrapper != NULL) { 129 if (OsSigWrapper(signo) == 0) { 130 /* ddx handled signal and wants us to continue */ 131 return; 132 } 133 } 134 135 /* log, cleanup, and abort */ 136 xorg_backtrace(); 137 138#ifdef SA_SIGINFO 139 if (sip->si_code == SI_USER) { 140 ErrorF("Recieved signal %d sent by process %ld, uid %ld\n", 141 signo, (long) sip->si_pid, (long) sip->si_uid); 142 } else { 143 switch (signo) { 144 case SIGSEGV: 145 case SIGBUS: 146 case SIGILL: 147 case SIGFPE: 148 ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr); 149 } 150 } 151#endif 152 153 FatalError("Caught signal %d (%s). Server aborting\n", 154 signo, strsignal(signo)); 155} 156 157void 158OsInit(void) 159{ 160 static Bool been_here = FALSE; 161 static char* devnull = "/dev/null"; 162 char fname[PATH_MAX]; 163 164 if (!been_here) { 165 struct sigaction act, oact; 166 int i; 167 int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, 168 SIGSYS, 169 SIGXCPU, 170 SIGXFSZ, 171#ifdef SIGEMT 172 SIGEMT, 173#endif 174 0 /* must be last */ }; 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#ifdef HAVE_BACKTRACE 190 /* 191 * initialize the backtracer, since the ctor calls dlopen(), which 192 * calls malloc(), which isn't signal-safe. 193 */ 194 do { 195 void *array; 196 backtrace(&array, 1); 197 } while (0); 198#endif 199 200#ifdef RTLD_DI_SETSIGNAL 201 /* Tell runtime linker to send a signal we can catch instead of SIGKILL 202 * for failures to load libraries/modules at runtime so we can clean up 203 * after ourselves. 204 */ 205 int failure_signal = SIGQUIT; 206 dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal); 207#endif 208 209#if !defined(__CYGWIN__) 210 fclose(stdin); 211 fclose(stdout); 212#endif 213 /* 214 * If a write of zero bytes to stderr returns non-zero, i.e. -1, 215 * then writing to stderr failed, and we'll write somewhere else 216 * instead. (Apparently this never happens in the Real World.) 217 */ 218 if (write (2, fname, 0) == -1) 219 { 220 FILE *err; 221 222 if (strlen (display) + strlen (ADMPATH) + 1 < sizeof fname) 223 sprintf (fname, ADMPATH, display); 224 else 225 strcpy (fname, devnull); 226 /* 227 * uses stdio to avoid os dependencies here, 228 * a real os would use 229 * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) 230 */ 231 if (!(err = fopen (fname, "a+"))) 232 err = fopen (devnull, "w"); 233 if (err && (fileno(err) != 2)) { 234 dup2 (fileno (err), 2); 235 fclose (err); 236 } 237#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__) 238 { 239 static char buf[BUFSIZ]; 240 setvbuf (stderr, buf, _IOLBF, BUFSIZ); 241 } 242#else 243 setlinebuf(stderr); 244#endif 245 } 246 247 if (getpgrp () == 0) 248 setpgid (0, 0); 249 250#ifdef RLIMIT_DATA 251 if (limitDataSpace >= 0) 252 { 253 struct rlimit rlim; 254 255 if (!getrlimit(RLIMIT_DATA, &rlim)) 256 { 257 if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max)) 258 rlim.rlim_cur = limitDataSpace; 259 else 260 rlim.rlim_cur = rlim.rlim_max; 261 (void)setrlimit(RLIMIT_DATA, &rlim); 262 } 263 } 264#endif 265#ifdef RLIMIT_STACK 266 if (limitStackSpace >= 0) 267 { 268 struct rlimit rlim; 269 270 if (!getrlimit(RLIMIT_STACK, &rlim)) 271 { 272 if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max)) 273 rlim.rlim_cur = limitStackSpace; 274 else 275 rlim.rlim_cur = rlim.rlim_max; 276 (void)setrlimit(RLIMIT_STACK, &rlim); 277 } 278 } 279#endif 280#ifdef RLIMIT_NOFILE 281 if (limitNoFile >= 0) 282 { 283 struct rlimit rlim; 284 285 if (!getrlimit(RLIMIT_NOFILE, &rlim)) 286 { 287 if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max)) 288 rlim.rlim_cur = limitNoFile; 289 else 290 rlim.rlim_cur = rlim.rlim_max; 291 (void)setrlimit(RLIMIT_NOFILE, &rlim); 292 } 293 } 294#endif 295 LockServer(); 296 been_here = TRUE; 297 } 298 TimerInit(); 299 OsVendorInit(); 300 /* 301 * No log file by default. OsVendorInit() should call LogInit() with the 302 * log file name if logging to a file is desired. 303 */ 304 LogInit(NULL, NULL); 305 SmartScheduleInit (); 306} 307 308void 309OsCleanup(Bool terminating) 310{ 311 if (terminating) 312 { 313 UnlockServer(); 314 } 315} 316