#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stdio.h>
#include <X11/X.h>
#include "os.h"
#include "osdep.h"
#include <X11/Xos.h>
#include <signal.h>
#include <errno.h>
#ifdef HAVE_DLFCN_H
# include <dlfcn.h>
#endif
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
#endif
#include "dixstruct.h"
#ifndef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif
#endif
#if !defined(SYSV) && !defined(WIN32)
#include <sys/resource.h>
#endif
#ifndef ADMPATH
#define ADMPATH "/usr/adm/X%smsgs"
#endif
extern char *display;
#ifdef RLIMIT_DATA
int limitDataSpace = -1;
#endif
#ifdef RLIMIT_STACK
int limitStackSpace = -1;
#endif
#ifdef RLIMIT_NOFILE
int limitNoFile = -1;
#endif
static OsSigWrapperPtr OsSigWrapper = NULL;
OsSigWrapperPtr
OsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper)
{
OsSigWrapperPtr oldSigWrapper = OsSigWrapper;
OsSigWrapper = newSigWrapper;
return oldSigWrapper;
}
static void
#ifdef SA_SIGINFO
OsSigHandler(int signo, siginfo_t *sip, void *unused)
#else
OsSigHandler(int signo)
#endif
{
#ifdef RTLD_DI_SETSIGNAL
const char *dlerr = dlerror();
if (dlerr) {
LogMessage(X_ERROR, "Dynamic loader error: %s\n", dlerr);
}
#endif
if (OsSigWrapper != NULL) {
if (OsSigWrapper(signo) == 0) {
return;
}
}
xorg_backtrace();
#ifdef SA_SIGINFO
if (sip->si_code == SI_USER) {
ErrorF("Recieved signal %d sent by process %ld, uid %ld\n",
signo, (long) sip->si_pid, (long) sip->si_uid);
} else {
switch (signo) {
case SIGSEGV:
case SIGBUS:
case SIGILL:
case SIGFPE:
ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr);
}
}
#endif
FatalError("Caught signal %d (%s). Server aborting\n",
signo, strsignal(signo));
}
void
OsInit(void)
{
static Bool been_here = FALSE;
static char* devnull = "/dev/null";
char fname[PATH_MAX];
if (!been_here) {
struct sigaction act, oact;
int i;
int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS,
SIGSYS,
SIGXCPU,
SIGXFSZ,
#ifdef SIGEMT
SIGEMT,
#endif
0 };
sigemptyset(&act.sa_mask);
#ifdef SA_SIGINFO
act.sa_sigaction = OsSigHandler;
act.sa_flags = SA_SIGINFO;
#else
act.sa_handler = OsSigHandler;
act.sa_flags = 0;
#endif
for (i = 0; siglist[i] != 0; i++) {
if (sigaction(siglist[i], &act, &oact)) {
ErrorF("failed to install signal handler for signal %d: %s\n",
siglist[i], strerror(errno));
}
}
#ifdef HAVE_BACKTRACE
do {
void *array;
backtrace(&array, 1);
} while (0);
#endif
#ifdef RTLD_DI_SETSIGNAL
int failure_signal = SIGQUIT;
dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal);
#endif
#if !defined(__CYGWIN__)
fclose(stdin);
fclose(stdout);
#endif
if (write (2, fname, 0) == -1)
{
FILE *err;
if (strlen (display) + strlen (ADMPATH) + 1 < sizeof fname)
sprintf (fname, ADMPATH, display);
else
strcpy (fname, devnull);
if (!(err = fopen (fname, "a+")))
err = fopen (devnull, "w");
if (err && (fileno(err) != 2)) {
dup2 (fileno (err), 2);
fclose (err);
}
#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__)
{
static char buf[BUFSIZ];
setvbuf (stderr, buf, _IOLBF, BUFSIZ);
}
#else
setlinebuf(stderr);
#endif
}
if (getpgrp () == 0)
setpgid (0, 0);
#ifdef RLIMIT_DATA
if (limitDataSpace >= 0)
{
struct rlimit rlim;
if (!getrlimit(RLIMIT_DATA, &rlim))
{
if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max))
rlim.rlim_cur = limitDataSpace;
else
rlim.rlim_cur = rlim.rlim_max;
(void)setrlimit(RLIMIT_DATA, &rlim);
}
}
#endif
#ifdef RLIMIT_STACK
if (limitStackSpace >= 0)
{
struct rlimit rlim;
if (!getrlimit(RLIMIT_STACK, &rlim))
{
if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max))
rlim.rlim_cur = limitStackSpace;
else
rlim.rlim_cur = rlim.rlim_max;
(void)setrlimit(RLIMIT_STACK, &rlim);
}
}
#endif
#ifdef RLIMIT_NOFILE
if (limitNoFile >= 0)
{
struct rlimit rlim;
if (!getrlimit(RLIMIT_NOFILE, &rlim))
{
if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max))
rlim.rlim_cur = limitNoFile;
else
rlim.rlim_cur = rlim.rlim_max;
(void)setrlimit(RLIMIT_NOFILE, &rlim);
}
}
#endif
LockServer();
been_here = TRUE;
}
TimerInit();
OsVendorInit();
LogInit(NULL, NULL);
SmartScheduleInit ();
}
void
OsCleanup(Bool terminating)
{
if (terminating)
{
UnlockServer();
}
}