osinit.c revision 35c4bbdf
105b261ecSmrg/*********************************************************** 205b261ecSmrg 305b261ecSmrgCopyright 1987, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg 2505b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 2605b261ecSmrg 2705b261ecSmrg All Rights Reserved 2805b261ecSmrg 2935c4bbdfSmrgPermission to use, copy, modify, and distribute this software and its 3035c4bbdfSmrgdocumentation for any purpose and without fee is hereby granted, 3105b261ecSmrgprovided that the above copyright notice appear in all copies and that 3235c4bbdfSmrgboth that copyright notice and this permission notice appear in 3305b261ecSmrgsupporting documentation, and that the name of Digital not be 3405b261ecSmrgused in advertising or publicity pertaining to distribution of the 3535c4bbdfSmrgsoftware without specific, written prior permission. 3605b261ecSmrg 3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4305b261ecSmrgSOFTWARE. 4405b261ecSmrg 4505b261ecSmrg******************************************************************/ 4605b261ecSmrg 4705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 4805b261ecSmrg#include <dix-config.h> 4905b261ecSmrg#endif 5005b261ecSmrg 5105b261ecSmrg#include <stdio.h> 5205b261ecSmrg#include <X11/X.h> 5305b261ecSmrg#include "os.h" 5405b261ecSmrg#include "osdep.h" 5505b261ecSmrg#include <X11/Xos.h> 566747b715Smrg#include <signal.h> 576747b715Smrg#include <errno.h> 586747b715Smrg#ifdef HAVE_DLFCN_H 5935c4bbdfSmrg#include <dlfcn.h> 606747b715Smrg#endif 616747b715Smrg#ifdef HAVE_BACKTRACE 626747b715Smrg#include <execinfo.h> 636747b715Smrg#endif 646747b715Smrg 6535c4bbdfSmrg#include "misc.h" 6605b261ecSmrg 6705b261ecSmrg#include "dixstruct.h" 6805b261ecSmrg 6935c4bbdfSmrg#if !defined(SYSV) && !defined(WIN32) 7005b261ecSmrg#include <sys/resource.h> 7105b261ecSmrg#endif 7205b261ecSmrg 7305b261ecSmrg#ifndef ADMPATH 7405b261ecSmrg#define ADMPATH "/usr/adm/X%smsgs" 7505b261ecSmrg#endif 7605b261ecSmrg 7705b261ecSmrgextern char *display; 7835c4bbdfSmrg 7905b261ecSmrg#ifdef RLIMIT_DATA 8005b261ecSmrgint limitDataSpace = -1; 8105b261ecSmrg#endif 8205b261ecSmrg#ifdef RLIMIT_STACK 8305b261ecSmrgint limitStackSpace = -1; 8405b261ecSmrg#endif 8505b261ecSmrg#ifdef RLIMIT_NOFILE 8605b261ecSmrgint limitNoFile = -1; 8705b261ecSmrg#endif 8805b261ecSmrg 8935c4bbdfSmrg/* The actual user defined max number of clients */ 9035c4bbdfSmrgint LimitClients = LIMITCLIENTS; 9135c4bbdfSmrg 926747b715Smrgstatic OsSigWrapperPtr OsSigWrapper = NULL; 936747b715Smrg 946747b715SmrgOsSigWrapperPtr 956747b715SmrgOsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper) 966747b715Smrg{ 976747b715Smrg OsSigWrapperPtr oldSigWrapper = OsSigWrapper; 986747b715Smrg 996747b715Smrg OsSigWrapper = newSigWrapper; 1006747b715Smrg 1016747b715Smrg return oldSigWrapper; 1026747b715Smrg} 1036747b715Smrg 1046747b715Smrg/* 1056747b715Smrg * OsSigHandler -- 1066747b715Smrg * Catch unexpected signals and exit or continue cleanly. 1076747b715Smrg */ 10835c4bbdfSmrg#if !defined(WIN32) || defined(__CYGWIN__) 1096747b715Smrgstatic void 1106747b715Smrg#ifdef SA_SIGINFO 11135c4bbdfSmrgOsSigHandler(int signo, siginfo_t * sip, void *unused) 1126747b715Smrg#else 1136747b715SmrgOsSigHandler(int signo) 1146747b715Smrg#endif 1156747b715Smrg{ 1166747b715Smrg#ifdef RTLD_DI_SETSIGNAL 11735c4bbdfSmrg const char *dlerr = dlerror(); 1186747b715Smrg 11935c4bbdfSmrg if (dlerr) { 12035c4bbdfSmrg LogMessageVerbSigSafe(X_ERROR, 1, "Dynamic loader error: %s\n", dlerr); 12135c4bbdfSmrg } 12235c4bbdfSmrg#endif /* RTLD_DI_SETSIGNAL */ 1236747b715Smrg 12435c4bbdfSmrg if (OsSigWrapper != NULL) { 12535c4bbdfSmrg if (OsSigWrapper(signo) == 0) { 12635c4bbdfSmrg /* ddx handled signal and wants us to continue */ 12735c4bbdfSmrg return; 12835c4bbdfSmrg } 12935c4bbdfSmrg } 1306747b715Smrg 13135c4bbdfSmrg /* log, cleanup, and abort */ 13235c4bbdfSmrg xorg_backtrace(); 1336747b715Smrg 1346747b715Smrg#ifdef SA_SIGINFO 13535c4bbdfSmrg if (sip->si_code == SI_USER) { 13635c4bbdfSmrg ErrorFSigSafe("Received signal %u sent by process %u, uid %u\n", signo, 13735c4bbdfSmrg sip->si_pid, sip->si_uid); 13835c4bbdfSmrg } 13935c4bbdfSmrg else { 14035c4bbdfSmrg switch (signo) { 14135c4bbdfSmrg case SIGSEGV: 14235c4bbdfSmrg case SIGBUS: 14335c4bbdfSmrg case SIGILL: 14435c4bbdfSmrg case SIGFPE: 14535c4bbdfSmrg ErrorFSigSafe("%s at address %p\n", strsignal(signo), sip->si_addr); 14635c4bbdfSmrg } 14735c4bbdfSmrg } 1486747b715Smrg#endif 1496747b715Smrg 15035c4bbdfSmrg FatalError("Caught signal %d (%s). Server aborting\n", 15135c4bbdfSmrg signo, strsignal(signo)); 1526747b715Smrg} 15335c4bbdfSmrg#endif /* !WIN32 || __CYGWIN__ */ 15435c4bbdfSmrg 15535c4bbdfSmrg#include "busfault.h" 1566747b715Smrg 15705b261ecSmrgvoid 15805b261ecSmrgOsInit(void) 15905b261ecSmrg{ 16005b261ecSmrg static Bool been_here = FALSE; 16135c4bbdfSmrg#ifndef XQUARTZ 16235c4bbdfSmrg static const char *devnull = "/dev/null"; 16305b261ecSmrg char fname[PATH_MAX]; 16435c4bbdfSmrg#endif 16505b261ecSmrg 1666747b715Smrg if (!been_here) { 16735c4bbdfSmrg#if !defined(WIN32) || defined(__CYGWIN__) 16835c4bbdfSmrg struct sigaction act, oact; 16935c4bbdfSmrg int i; 17035c4bbdfSmrg 17135c4bbdfSmrg int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, 17235c4bbdfSmrg SIGSYS, 17335c4bbdfSmrg SIGXCPU, 17435c4bbdfSmrg SIGXFSZ, 1756747b715Smrg#ifdef SIGEMT 17635c4bbdfSmrg SIGEMT, 1776747b715Smrg#endif 17835c4bbdfSmrg 0 /* must be last */ 17935c4bbdfSmrg }; 18035c4bbdfSmrg sigemptyset(&act.sa_mask); 1816747b715Smrg#ifdef SA_SIGINFO 18235c4bbdfSmrg act.sa_sigaction = OsSigHandler; 18335c4bbdfSmrg act.sa_flags = SA_SIGINFO; 1846747b715Smrg#else 1856747b715Smrg act.sa_handler = OsSigHandler; 1866747b715Smrg act.sa_flags = 0; 1876747b715Smrg#endif 18835c4bbdfSmrg for (i = 0; siglist[i] != 0; i++) { 18935c4bbdfSmrg if (sigaction(siglist[i], &act, &oact)) { 19035c4bbdfSmrg ErrorF("failed to install signal handler for signal %d: %s\n", 19135c4bbdfSmrg siglist[i], strerror(errno)); 19235c4bbdfSmrg } 19335c4bbdfSmrg } 19435c4bbdfSmrg#endif /* !WIN32 || __CYGWIN__ */ 19535c4bbdfSmrg#ifdef BUSFAULT 19635c4bbdfSmrg busfault_init(); 19735c4bbdfSmrg#endif 19835c4bbdfSmrg 1996747b715Smrg#ifdef HAVE_BACKTRACE 20035c4bbdfSmrg /* 20135c4bbdfSmrg * initialize the backtracer, since the ctor calls dlopen(), which 20235c4bbdfSmrg * calls malloc(), which isn't signal-safe. 20335c4bbdfSmrg */ 20435c4bbdfSmrg do { 20535c4bbdfSmrg void *array; 20635c4bbdfSmrg 20735c4bbdfSmrg backtrace(&array, 1); 20835c4bbdfSmrg } while (0); 2096747b715Smrg#endif 2106747b715Smrg 2116747b715Smrg#ifdef RTLD_DI_SETSIGNAL 21235c4bbdfSmrg /* Tell runtime linker to send a signal we can catch instead of SIGKILL 21335c4bbdfSmrg * for failures to load libraries/modules at runtime so we can clean up 21435c4bbdfSmrg * after ourselves. 21535c4bbdfSmrg */ 21635c4bbdfSmrg { 21735c4bbdfSmrg int failure_signal = SIGQUIT; 21835c4bbdfSmrg 21935c4bbdfSmrg dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal); 22035c4bbdfSmrg } 22105b261ecSmrg#endif 22205b261ecSmrg 22335c4bbdfSmrg#if !defined(XQUARTZ) /* STDIN is already /dev/null and STDOUT/STDERR is managed by console_redirect.c */ 22435c4bbdfSmrg# if defined(__APPLE__) 22535c4bbdfSmrg int devnullfd = open(devnull, O_RDWR, 0); 22635c4bbdfSmrg assert(devnullfd > 2); 22735c4bbdfSmrg 22835c4bbdfSmrg dup2(devnullfd, STDIN_FILENO); 22935c4bbdfSmrg dup2(devnullfd, STDOUT_FILENO); 23035c4bbdfSmrg close(devnullfd); 23135c4bbdfSmrg# elif !defined(__CYGWIN__) 23235c4bbdfSmrg fclose(stdin); 23335c4bbdfSmrg fclose(stdout); 23435c4bbdfSmrg# endif 23535c4bbdfSmrg /* 23635c4bbdfSmrg * If a write of zero bytes to stderr returns non-zero, i.e. -1, 23735c4bbdfSmrg * then writing to stderr failed, and we'll write somewhere else 23835c4bbdfSmrg * instead. (Apparently this never happens in the Real World.) 23935c4bbdfSmrg */ 24035c4bbdfSmrg if (write(2, fname, 0) == -1) { 24135c4bbdfSmrg FILE *err; 24235c4bbdfSmrg 24335c4bbdfSmrg if (strlen(display) + strlen(ADMPATH) + 1 < sizeof fname) 24435c4bbdfSmrg snprintf(fname, sizeof(fname), ADMPATH, display); 24535c4bbdfSmrg else 24635c4bbdfSmrg strcpy(fname, devnull); 24735c4bbdfSmrg /* 24835c4bbdfSmrg * uses stdio to avoid os dependencies here, 24935c4bbdfSmrg * a real os would use 25035c4bbdfSmrg * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) 25135c4bbdfSmrg */ 25235c4bbdfSmrg if (!(err = fopen(fname, "a+"))) 25335c4bbdfSmrg err = fopen(devnull, "w"); 25435c4bbdfSmrg if (err && (fileno(err) != 2)) { 25535c4bbdfSmrg dup2(fileno(err), 2); 25635c4bbdfSmrg fclose(err); 25735c4bbdfSmrg } 25805b261ecSmrg#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__) 25935c4bbdfSmrg { 26035c4bbdfSmrg static char buf[BUFSIZ]; 26135c4bbdfSmrg 26235c4bbdfSmrg setvbuf(stderr, buf, _IOLBF, BUFSIZ); 26335c4bbdfSmrg } 26405b261ecSmrg#else 26535c4bbdfSmrg setlinebuf(stderr); 26605b261ecSmrg#endif 26735c4bbdfSmrg } 26835c4bbdfSmrg#endif /* !XQUARTZ */ 26905b261ecSmrg 27035c4bbdfSmrg#if !defined(WIN32) || defined(__CYGWIN__) 27135c4bbdfSmrg if (getpgrp() == 0) 27235c4bbdfSmrg setpgid(0, 0); 27335c4bbdfSmrg#endif 27405b261ecSmrg 27505b261ecSmrg#ifdef RLIMIT_DATA 27635c4bbdfSmrg if (limitDataSpace >= 0) { 27735c4bbdfSmrg struct rlimit rlim; 27835c4bbdfSmrg 27935c4bbdfSmrg if (!getrlimit(RLIMIT_DATA, &rlim)) { 28035c4bbdfSmrg if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max)) 28135c4bbdfSmrg rlim.rlim_cur = limitDataSpace; 28235c4bbdfSmrg else 28335c4bbdfSmrg rlim.rlim_cur = rlim.rlim_max; 28435c4bbdfSmrg (void) setrlimit(RLIMIT_DATA, &rlim); 28535c4bbdfSmrg } 28635c4bbdfSmrg } 28705b261ecSmrg#endif 28805b261ecSmrg#ifdef RLIMIT_STACK 28935c4bbdfSmrg if (limitStackSpace >= 0) { 29035c4bbdfSmrg struct rlimit rlim; 29135c4bbdfSmrg 29235c4bbdfSmrg if (!getrlimit(RLIMIT_STACK, &rlim)) { 29335c4bbdfSmrg if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max)) 29435c4bbdfSmrg rlim.rlim_cur = limitStackSpace; 29535c4bbdfSmrg else 29635c4bbdfSmrg rlim.rlim_cur = rlim.rlim_max; 29735c4bbdfSmrg (void) setrlimit(RLIMIT_STACK, &rlim); 29835c4bbdfSmrg } 29935c4bbdfSmrg } 30005b261ecSmrg#endif 30105b261ecSmrg#ifdef RLIMIT_NOFILE 30235c4bbdfSmrg if (limitNoFile >= 0) { 30335c4bbdfSmrg struct rlimit rlim; 30435c4bbdfSmrg 30535c4bbdfSmrg if (!getrlimit(RLIMIT_NOFILE, &rlim)) { 30635c4bbdfSmrg if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max)) 30735c4bbdfSmrg rlim.rlim_cur = limitNoFile; 30835c4bbdfSmrg else 30935c4bbdfSmrg rlim.rlim_cur = rlim.rlim_max; 31035c4bbdfSmrg (void) setrlimit(RLIMIT_NOFILE, &rlim); 31135c4bbdfSmrg } 31235c4bbdfSmrg } 31305b261ecSmrg#endif 31435c4bbdfSmrg LockServer(); 31535c4bbdfSmrg been_here = TRUE; 31605b261ecSmrg } 31705b261ecSmrg TimerInit(); 31805b261ecSmrg OsVendorInit(); 31935c4bbdfSmrg OsResetSignals(); 32005b261ecSmrg /* 32105b261ecSmrg * No log file by default. OsVendorInit() should call LogInit() with the 32205b261ecSmrg * log file name if logging to a file is desired. 32305b261ecSmrg */ 32405b261ecSmrg LogInit(NULL, NULL); 32535c4bbdfSmrg SmartScheduleInit(); 32605b261ecSmrg} 32705b261ecSmrg 32805b261ecSmrgvoid 32905b261ecSmrgOsCleanup(Bool terminating) 33005b261ecSmrg{ 33135c4bbdfSmrg if (terminating) { 33235c4bbdfSmrg UnlockServer(); 33305b261ecSmrg } 33405b261ecSmrg} 335