• Mike Gabriel's avatar
    dix/os: backport various signal handling and smart scheduler changes from X.org · 366067b7
    Mike Gabriel authored
     Backported from X.org:
    
     commit 6178b1c91cfc9e860914acc6f0be2f2d2e07a124
     Author: Adam Jackson <ajax@redhat.com>
     Date:   Tue Jun 7 15:52:11 2016 -0400
    
        dix: Use OsSignal() not signal()
    
        As the man page for the latter states:
    
            The effects of signal() in a multithreaded process are unspecified.
    
        We already have an interface to call sigaction() instead, use it.
    Signed-off-by: 's avatarAdam Jackson <ajax@redhat.com>
    Reviewed-by: 's avatarKeith Packard <keithp@keithp.com>
    
     commit e10ba9e4b52269b2ac75c4802dce4ca47d169657
     Author: Keith Packard <keithp@keithp.com>
     Date:   Wed Nov 11 22:02:01 2015 -0800
    
        Remove non-smart scheduler. Don't require setitimer.
    
        This allows the server to call GetTimeInMillis() after each request is
        processed to avoid needing setitimer. -dumbSched now turns off the
        setitimer.
    Reviewed-by: 's avatarAdam Jackson <ajax@redhat.com>
    Signed-off-by: 's avatarKeith Packard <keithp@keithp.com>
    
     commit 1f915e8b524dd02011158aa038935970684c7630
     Author: Daniel Drake <drake@endlessm.com>
     Date:   Wed May 20 13:16:12 2015 -0600
    
        Keep SIGALRM restart flag after Popen
    
        Commit 94ab7455 added SA_RESTART to the SIGALRM handler.  However, the
        Popen code tears down and recreates the SIGALRM handler via OsSignal(),
        and this flag is dropped at this time.
    
        Clean the code to use just a single codepath for creating this signal
        handler, always applying SA_RESTART.
    
        [ajax: Fixed commit id]
    Reviewed-by: 's avatarAdam Jackson <ajax@redhat.com>
    Signed-off-by: 's avatarDaniel Drake <drake@endlessm.com>
    
     commit 94ab7455abc213fc96760e29ab2e943ec682fb22
     Author: Daniel Drake <drake@endlessm.com>
     Date:   Tue May 12 16:39:22 2015 -0600
    
        Allow system call restarts upon signal interruption
    
        The X server frequently deals with SIGIO and SIGALRM interruptions.
        If process execution is inside certain blocking system calls
        when these signals arrive, e.g. with the kernel blocked on
        a contended semaphore, the system calls will be interrupted.
    
        Some system calls are automatically restartable (the kernel re-executes
        them with the same parameters once the signal handler returns) but
        only if the signal handler allows it.
    
        Set SA_RESTART on the signal handlers to enable this convenient
        behaviour.
    Reviewed-by: 's avatarAdam Jackson <ajax@redhat.com>
    Signed-off-by: 's avatarDaniel Drake <drake@endlessm.com>
    
     commit a6c71ce5d2d2fe89e07a2ef5041c915acc3dc686
     Author: Tiago Vignatti <tiago.vignatti@nokia.com>
     Date:   Mon Mar 28 19:21:28 2011 +0300
    
        os: fix memory and fd leaks in Popen
    Signed-off-by: 's avatarTiago Vignatti <tiago.vignatti@nokia.com>
    Reviewed-by: 's avatarPeter Hutterer <peter.hutterer@who-t.net>
    Reviewed-by: 's avatarNicolas Peninguy <nico@lostgeeks.org>
    
     commit c9051b684b524549eab6d5b88ee3e195a6f6fbe8
     Author: Alan Coopersmith <alan.coopersmith@sun.com>
     Date:   Wed Nov 5 18:25:57 2008 -0800
    
        Use OsSignal in Popen/Pclose to avoid SysV signal() stupidity
    
     commit 0e9ef65fa583bf2393dd0fda82df6f092387b425
     Author: Keith Packard <keithp@koto.keithp.com>
     Date:   Wed Nov 7 16:33:10 2007 -0800
    
        Don't frob timers unless SmartSchedule is running
    
     commit 2338d5c9914e2a43c3a4f7ee0f4355ad0a1ad9e7
     Author: Arjan van de Ven <arjan@linux.intel.com>
     Date:   Sun Oct 28 09:37:52 2007 +0100
    
        reduce wakeups from smart scheduler
    
        The smart scheduler itimer currently always fires after each request
        (which in turn causes the CPU to wake out of idle, burning precious
        power). Rather than doing this, just stop the timer before going into
        the select() portion of the WaitFor loop. It's a cheap system call, and
        it will only get called if there's no more commands batched up from the
        active fd.
    
        This change also allows some of the functions to be simplified;
        setitimer() will only fail if it's passed invalid data, and we don't do
        that... so make it void and remove all the conditional code that deals
        with failure.
    
        The change also allows us to remove a few variables that were used for
        housekeeping between the signal handler and the main loop.
    Signed-off-by: 's avatarKeith Packard <keithp@koto.keithp.com>
    
     **Note**: The above change also required ABI changes in hw/nxagent/.
    
     commit abe0a51f3f790f8c055289465e130177c4b647cc
     Author: Ben Byer <bbyer@bbyer.apple.com>
     Date:   Fri Sep 21 17:07:36 2007 -0700
    
        So, like, checking return codes of system calls (signal, etc) is good.
        Also, only restore an old signal handler if one was actually set
        (prevents the server from dying on OS X).
    
     commit 6da39c67905500ab2db00a45cda4a9f756cdde96
     Author: Eric Anholt <eric@anholt.net>
     Date:   Wed Sep 12 13:23:13 2007 +0000
    
        Fix build on FreeBSD after Popen changes.
    
     commit a5b8053606d6e786cdcf6734f271acc05f9cc588
     Author: Adam Jackson <ajax@benzedrine.nwnk.net>
     Date:   Tue Sep 11 11:37:06 2007 -0400
    
        Ignore - not just block - SIGALRM around Popen()/Pclose().
    
        Because our "popen" implementation uses stdio, and because nobody's stdio
        library is capable of surviving signals, we need to make absolutely sure
        that we hide the SIGALRM from the smart scheduler.  Otherwise, when you
        open a menu in openoffice, and it recompiles XKB to deal with the
        accelerators, and you popen xkbcomp because we suck, then the scheduler
        will tell you you're taking forever doing something stupid, and the
        wait() code will get confused, and input will hang and your CPU usage
        slams to 100%.  Down, not across.
    Backported-to-NX-by: 's avatarMike Gabriel <mike.gabriel@das-netzwerkteam.de>
    366067b7
osinit.c 5.74 KB
/***********************************************************

Copyright 1987, 1998  The Open Group

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.


Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and without fee is hereby granted, 
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in 
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.  

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/

#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif

#include <stdio.h>
#include <nx-X11/X.h>
#include "os.h"
#include "osdep.h"
#include <nx-X11/Xos.h>

#include "dixstruct.h"

#ifndef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif
#endif

#if defined(__SCO__)
#include <sys/wait.h>
#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

void
OsInit(void)
{
    static Bool been_here = FALSE;
    static char* admpath = ADMPATH;
    static char* devnull = "/dev/null";
    char fname[PATH_MAX];

#ifdef macII
    set42sig();
#endif

    if (!been_here) {

	InitNotifyFds();

#if !defined(__SCO__) && !defined(__CYGWIN__) && !defined(__UNIXWARE__)
	fclose(stdin);
	fclose(stdout);
#endif


	/* 
	 * If a write of zero bytes to stderr returns non-zero, i.e. -1, 
	 * then writing to stderr failed, and we'll write somewhere else 
	 * instead. (Apparently this never happens in the Real World.)
	 */
	if (write (2, fname, 0) == -1) 
	{
	    FILE *err;

	    if (strlen (display) + strlen (admpath) + 1 < sizeof fname)
		sprintf (fname, admpath, display);
	    else
		strcpy (fname, devnull);
	    /*
	     * uses stdio to avoid os dependencies here,
	     * a real os would use
 	     *  open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666)
	     */
	    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
	}

#ifndef X_NOT_POSIX
	if (getpgrp () == 0)
	    setpgid (0, 0);
#else
#if !defined(SYSV) && !defined(WIN32)
	if (getpgrp (0) == 0)
	    setpgrp (0, getpid ());
#endif
#endif

#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;
#if 0
		if (rlim.rlim_cur > MAXSOCKS)
		    rlim.rlim_cur = MAXSOCKS;
#endif
		(void)setrlimit(RLIMIT_NOFILE, &rlim);
	    }
	}
#endif
#ifdef SERVER_LOCK
	LockServer();
#endif
	been_here = TRUE;
    }
    TimerInit();
#ifdef DDXOSINIT
    OsVendorInit();
#endif
    /*
     * No log file by default.  OsVendorInit() should call LogInit() with the
     * log file name if logging to a file is desired.
     */
    LogInit(NULL, NULL);
    SmartScheduleInit();

    OsInitAllocator();
}

void
OsCleanup(Bool terminating)
{
#ifdef SERVER_LOCK
    if (terminating)
    {
	UnlockServer();
    }
#endif
}