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