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" 551b5d61b8Smrg#include "opaque.h" 5605b261ecSmrg#include <X11/Xos.h> 576747b715Smrg#include <signal.h> 586747b715Smrg#include <errno.h> 596747b715Smrg#ifdef HAVE_DLFCN_H 6035c4bbdfSmrg#include <dlfcn.h> 616747b715Smrg#endif 626747b715Smrg#ifdef HAVE_BACKTRACE 636747b715Smrg#include <execinfo.h> 646747b715Smrg#endif 656747b715Smrg 6635c4bbdfSmrg#include "misc.h" 6705b261ecSmrg 6805b261ecSmrg#include "dixstruct.h" 6905b261ecSmrg 7035c4bbdfSmrg#if !defined(SYSV) && !defined(WIN32) 7105b261ecSmrg#include <sys/resource.h> 7205b261ecSmrg#endif 7305b261ecSmrg 7405b261ecSmrg#ifndef ADMPATH 7505b261ecSmrg#define ADMPATH "/usr/adm/X%smsgs" 7605b261ecSmrg#endif 7705b261ecSmrg 7805b261ecSmrg#ifdef RLIMIT_DATA 7905b261ecSmrgint limitDataSpace = -1; 8005b261ecSmrg#endif 8105b261ecSmrg#ifdef RLIMIT_STACK 8205b261ecSmrgint limitStackSpace = -1; 8305b261ecSmrg#endif 8405b261ecSmrg#ifdef RLIMIT_NOFILE 8505b261ecSmrgint limitNoFile = -1; 8605b261ecSmrg#endif 8705b261ecSmrg 8835c4bbdfSmrg/* The actual user defined max number of clients */ 8935c4bbdfSmrgint LimitClients = LIMITCLIENTS; 9035c4bbdfSmrg 916747b715Smrgstatic OsSigWrapperPtr OsSigWrapper = NULL; 926747b715Smrg 936747b715SmrgOsSigWrapperPtr 946747b715SmrgOsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper) 956747b715Smrg{ 966747b715Smrg OsSigWrapperPtr oldSigWrapper = OsSigWrapper; 976747b715Smrg 986747b715Smrg OsSigWrapper = newSigWrapper; 996747b715Smrg 1006747b715Smrg return oldSigWrapper; 1016747b715Smrg} 1026747b715Smrg 1036747b715Smrg/* 1046747b715Smrg * OsSigHandler -- 1056747b715Smrg * Catch unexpected signals and exit or continue cleanly. 1066747b715Smrg */ 10735c4bbdfSmrg#if !defined(WIN32) || defined(__CYGWIN__) 1086747b715Smrgstatic void 1096747b715Smrg#ifdef SA_SIGINFO 11035c4bbdfSmrgOsSigHandler(int signo, siginfo_t * sip, void *unused) 1116747b715Smrg#else 1126747b715SmrgOsSigHandler(int signo) 1136747b715Smrg#endif 1146747b715Smrg{ 1156747b715Smrg#ifdef RTLD_DI_SETSIGNAL 1161b5d61b8Smrg# define SIGNAL_FOR_RTLD_ERROR SIGQUIT 1171b5d61b8Smrg if (signo == SIGNAL_FOR_RTLD_ERROR) { 1181b5d61b8Smrg const char *dlerr = dlerror(); 1196747b715Smrg 1201b5d61b8Smrg if (dlerr) { 1211b5d61b8Smrg LogMessageVerbSigSafe(X_ERROR, 1, 1221b5d61b8Smrg "Dynamic loader error: %s\n", dlerr); 1231b5d61b8Smrg } 12435c4bbdfSmrg } 12535c4bbdfSmrg#endif /* RTLD_DI_SETSIGNAL */ 1266747b715Smrg 12735c4bbdfSmrg if (OsSigWrapper != NULL) { 12835c4bbdfSmrg if (OsSigWrapper(signo) == 0) { 12935c4bbdfSmrg /* ddx handled signal and wants us to continue */ 13035c4bbdfSmrg return; 13135c4bbdfSmrg } 13235c4bbdfSmrg } 1336747b715Smrg 13435c4bbdfSmrg /* log, cleanup, and abort */ 13535c4bbdfSmrg xorg_backtrace(); 1366747b715Smrg 1376747b715Smrg#ifdef SA_SIGINFO 13835c4bbdfSmrg if (sip->si_code == SI_USER) { 13935c4bbdfSmrg ErrorFSigSafe("Received signal %u sent by process %u, uid %u\n", signo, 14035c4bbdfSmrg sip->si_pid, sip->si_uid); 14135c4bbdfSmrg } 14235c4bbdfSmrg else { 14335c4bbdfSmrg switch (signo) { 14435c4bbdfSmrg case SIGSEGV: 14535c4bbdfSmrg case SIGBUS: 14635c4bbdfSmrg case SIGILL: 14735c4bbdfSmrg case SIGFPE: 14835c4bbdfSmrg ErrorFSigSafe("%s at address %p\n", strsignal(signo), sip->si_addr); 14935c4bbdfSmrg } 15035c4bbdfSmrg } 1516747b715Smrg#endif 1526747b715Smrg 1531b5d61b8Smrg if (signo != SIGQUIT) 1541b5d61b8Smrg CoreDump = TRUE; 1551b5d61b8Smrg 15635c4bbdfSmrg FatalError("Caught signal %d (%s). Server aborting\n", 15735c4bbdfSmrg signo, strsignal(signo)); 1586747b715Smrg} 15935c4bbdfSmrg#endif /* !WIN32 || __CYGWIN__ */ 16035c4bbdfSmrg 16135c4bbdfSmrg#include "busfault.h" 1626747b715Smrg 16305b261ecSmrgvoid 16405b261ecSmrgOsInit(void) 16505b261ecSmrg{ 16605b261ecSmrg static Bool been_here = FALSE; 16735c4bbdfSmrg#ifndef XQUARTZ 16835c4bbdfSmrg static const char *devnull = "/dev/null"; 16905b261ecSmrg char fname[PATH_MAX]; 17035c4bbdfSmrg#endif 17105b261ecSmrg 1726747b715Smrg if (!been_here) { 17335c4bbdfSmrg#if !defined(WIN32) || defined(__CYGWIN__) 17435c4bbdfSmrg struct sigaction act, oact; 17535c4bbdfSmrg int i; 17635c4bbdfSmrg 17735c4bbdfSmrg int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, 1781b5d61b8Smrg SIGABRT, 17935c4bbdfSmrg SIGSYS, 18035c4bbdfSmrg SIGXCPU, 18135c4bbdfSmrg SIGXFSZ, 1826747b715Smrg#ifdef SIGEMT 18335c4bbdfSmrg SIGEMT, 1846747b715Smrg#endif 18535c4bbdfSmrg 0 /* must be last */ 18635c4bbdfSmrg }; 18735c4bbdfSmrg sigemptyset(&act.sa_mask); 1886747b715Smrg#ifdef SA_SIGINFO 18935c4bbdfSmrg act.sa_sigaction = OsSigHandler; 19035c4bbdfSmrg act.sa_flags = SA_SIGINFO; 1916747b715Smrg#else 1926747b715Smrg act.sa_handler = OsSigHandler; 1936747b715Smrg act.sa_flags = 0; 1946747b715Smrg#endif 19535c4bbdfSmrg for (i = 0; siglist[i] != 0; i++) { 19635c4bbdfSmrg if (sigaction(siglist[i], &act, &oact)) { 19735c4bbdfSmrg ErrorF("failed to install signal handler for signal %d: %s\n", 19835c4bbdfSmrg siglist[i], strerror(errno)); 19935c4bbdfSmrg } 20035c4bbdfSmrg } 20135c4bbdfSmrg#endif /* !WIN32 || __CYGWIN__ */ 20235c4bbdfSmrg#ifdef BUSFAULT 20335c4bbdfSmrg busfault_init(); 20435c4bbdfSmrg#endif 2051b5d61b8Smrg server_poll = ospoll_create(); 2061b5d61b8Smrg if (!server_poll) 2071b5d61b8Smrg FatalError("failed to allocate poll structure"); 20835c4bbdfSmrg 2096747b715Smrg#ifdef HAVE_BACKTRACE 21035c4bbdfSmrg /* 21135c4bbdfSmrg * initialize the backtracer, since the ctor calls dlopen(), which 21235c4bbdfSmrg * calls malloc(), which isn't signal-safe. 21335c4bbdfSmrg */ 21435c4bbdfSmrg do { 21535c4bbdfSmrg void *array; 21635c4bbdfSmrg 21735c4bbdfSmrg backtrace(&array, 1); 21835c4bbdfSmrg } while (0); 2196747b715Smrg#endif 2206747b715Smrg 2216747b715Smrg#ifdef RTLD_DI_SETSIGNAL 22235c4bbdfSmrg /* Tell runtime linker to send a signal we can catch instead of SIGKILL 22335c4bbdfSmrg * for failures to load libraries/modules at runtime so we can clean up 22435c4bbdfSmrg * after ourselves. 22535c4bbdfSmrg */ 22635c4bbdfSmrg { 2271b5d61b8Smrg int failure_signal = SIGNAL_FOR_RTLD_ERROR; 22835c4bbdfSmrg 22935c4bbdfSmrg dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal); 23035c4bbdfSmrg } 23105b261ecSmrg#endif 23205b261ecSmrg 23335c4bbdfSmrg#if !defined(XQUARTZ) /* STDIN is already /dev/null and STDOUT/STDERR is managed by console_redirect.c */ 23435c4bbdfSmrg /* 23535c4bbdfSmrg * If a write of zero bytes to stderr returns non-zero, i.e. -1, 23635c4bbdfSmrg * then writing to stderr failed, and we'll write somewhere else 23735c4bbdfSmrg * instead. (Apparently this never happens in the Real World.) 23835c4bbdfSmrg */ 23935c4bbdfSmrg if (write(2, fname, 0) == -1) { 24035c4bbdfSmrg FILE *err; 24135c4bbdfSmrg 24235c4bbdfSmrg if (strlen(display) + strlen(ADMPATH) + 1 < sizeof fname) 24335c4bbdfSmrg snprintf(fname, sizeof(fname), ADMPATH, display); 24435c4bbdfSmrg else 24535c4bbdfSmrg strcpy(fname, devnull); 24635c4bbdfSmrg /* 24735c4bbdfSmrg * uses stdio to avoid os dependencies here, 24835c4bbdfSmrg * a real os would use 24935c4bbdfSmrg * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) 25035c4bbdfSmrg */ 25135c4bbdfSmrg if (!(err = fopen(fname, "a+"))) 25235c4bbdfSmrg err = fopen(devnull, "w"); 25335c4bbdfSmrg if (err && (fileno(err) != 2)) { 25435c4bbdfSmrg dup2(fileno(err), 2); 25535c4bbdfSmrg fclose(err); 25635c4bbdfSmrg } 25705b261ecSmrg#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__) 25835c4bbdfSmrg { 25935c4bbdfSmrg static char buf[BUFSIZ]; 26035c4bbdfSmrg 26135c4bbdfSmrg setvbuf(stderr, buf, _IOLBF, BUFSIZ); 26235c4bbdfSmrg } 26305b261ecSmrg#else 26435c4bbdfSmrg setlinebuf(stderr); 26505b261ecSmrg#endif 26635c4bbdfSmrg } 26735c4bbdfSmrg#endif /* !XQUARTZ */ 26805b261ecSmrg 26935c4bbdfSmrg#if !defined(WIN32) || defined(__CYGWIN__) 27035c4bbdfSmrg if (getpgrp() == 0) 27135c4bbdfSmrg setpgid(0, 0); 27235c4bbdfSmrg#endif 27305b261ecSmrg 27405b261ecSmrg#ifdef RLIMIT_DATA 27535c4bbdfSmrg if (limitDataSpace >= 0) { 27635c4bbdfSmrg struct rlimit rlim; 27735c4bbdfSmrg 27835c4bbdfSmrg if (!getrlimit(RLIMIT_DATA, &rlim)) { 27935c4bbdfSmrg if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max)) 28035c4bbdfSmrg rlim.rlim_cur = limitDataSpace; 28135c4bbdfSmrg else 28235c4bbdfSmrg rlim.rlim_cur = rlim.rlim_max; 28335c4bbdfSmrg (void) setrlimit(RLIMIT_DATA, &rlim); 28435c4bbdfSmrg } 28535c4bbdfSmrg } 28605b261ecSmrg#endif 28705b261ecSmrg#ifdef RLIMIT_STACK 28835c4bbdfSmrg if (limitStackSpace >= 0) { 28935c4bbdfSmrg struct rlimit rlim; 29035c4bbdfSmrg 29135c4bbdfSmrg if (!getrlimit(RLIMIT_STACK, &rlim)) { 29235c4bbdfSmrg if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max)) 29335c4bbdfSmrg rlim.rlim_cur = limitStackSpace; 29435c4bbdfSmrg else 29535c4bbdfSmrg rlim.rlim_cur = rlim.rlim_max; 29635c4bbdfSmrg (void) setrlimit(RLIMIT_STACK, &rlim); 29735c4bbdfSmrg } 29835c4bbdfSmrg } 29905b261ecSmrg#endif 30005b261ecSmrg#ifdef RLIMIT_NOFILE 30135c4bbdfSmrg if (limitNoFile >= 0) { 30235c4bbdfSmrg struct rlimit rlim; 30335c4bbdfSmrg 30435c4bbdfSmrg if (!getrlimit(RLIMIT_NOFILE, &rlim)) { 30535c4bbdfSmrg if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max)) 30635c4bbdfSmrg rlim.rlim_cur = limitNoFile; 30735c4bbdfSmrg else 30835c4bbdfSmrg rlim.rlim_cur = rlim.rlim_max; 30935c4bbdfSmrg (void) setrlimit(RLIMIT_NOFILE, &rlim); 31035c4bbdfSmrg } 31135c4bbdfSmrg } 31205b261ecSmrg#endif 31335c4bbdfSmrg LockServer(); 31435c4bbdfSmrg been_here = TRUE; 31505b261ecSmrg } 31605b261ecSmrg TimerInit(); 31705b261ecSmrg OsVendorInit(); 31835c4bbdfSmrg OsResetSignals(); 31905b261ecSmrg /* 32005b261ecSmrg * No log file by default. OsVendorInit() should call LogInit() with the 32105b261ecSmrg * log file name if logging to a file is desired. 32205b261ecSmrg */ 32305b261ecSmrg LogInit(NULL, NULL); 32435c4bbdfSmrg SmartScheduleInit(); 32505b261ecSmrg} 32605b261ecSmrg 32705b261ecSmrgvoid 32805b261ecSmrgOsCleanup(Bool terminating) 32905b261ecSmrg{ 33035c4bbdfSmrg if (terminating) { 33135c4bbdfSmrg UnlockServer(); 33205b261ecSmrg } 33305b261ecSmrg} 334