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