From 8996f80a5e3b205cb580aba34aa21d165ef78cfb Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Wed, 15 Feb 2017 14:42:48 +0000 Subject: Rework local client id finding code to be more uniform Backport of X.org commit: commit 2d93e69690d2c5d4a89a795ede6423796528e5df Author: Alan Coopersmith Date: Thu Sep 27 16:47:06 2007 -0700 Rework local client id finding code to be more uniform Backported-to-NX-by: Mike Gabriel Note: This commit also switches client_uid_string's size from 32 to 64 chars, as found in this X.org commit (spotted by Mihai Moldovan during code review): commit a7b944f0d96c3e0e15e75378a04def1ac96089fb Author: Alan Coopersmith Date: Wed Nov 1 16:17:49 2006 -0800 If getpeerucred() is available, include pid & zoneid in audit messages too --- nx-X11/programs/Xserver/include/os.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'nx-X11/programs/Xserver/include') diff --git a/nx-X11/programs/Xserver/include/os.h b/nx-X11/programs/Xserver/include/os.h index 99003922f..af84f54c0 100644 --- a/nx-X11/programs/Xserver/include/os.h +++ b/nx-X11/programs/Xserver/include/os.h @@ -321,6 +321,24 @@ extern int LocalClient(ClientPtr /* client */); extern int LocalClientCred(ClientPtr, int *, int *); +#define LCC_UID_SET (1 << 0) +#define LCC_GID_SET (1 << 1) +#define LCC_PID_SET (1 << 2) +#define LCC_ZID_SET (1 << 3) + +typedef struct { + int fieldsSet; /* Bit mask of fields set */ + int euid; /* Effective uid */ + int egid; /* Primary effective group id */ + int nSuppGids; /* Number of supplementary group ids */ + int *pSuppGids; /* Array of supplementary group ids */ + int pid; /* Process id */ + int zoneid; /* Only set on Solaris 10 & later */ +} LocalClientCredRec; + +extern int GetLocalClientCreds(ClientPtr, LocalClientCredRec **); +extern void FreeLocalClientCreds(LocalClientCredRec *); + extern int ChangeAccessControl(ClientPtr /*client*/, int /*fEnabled*/); extern int GetAccessControl(void); -- cgit v1.2.3 From 366067b7c3678148bff858239e3c16e0d6043e03 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Thu, 16 Feb 2017 15:21:34 +0000 Subject: dix/os: backport various signal handling and smart scheduler changes from X.org Backported from X.org: commit 6178b1c91cfc9e860914acc6f0be2f2d2e07a124 Author: Adam Jackson 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: Adam Jackson Reviewed-by: Keith Packard commit e10ba9e4b52269b2ac75c4802dce4ca47d169657 Author: Keith Packard 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: Adam Jackson Signed-off-by: Keith Packard commit 1f915e8b524dd02011158aa038935970684c7630 Author: Daniel Drake 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: Adam Jackson Signed-off-by: Daniel Drake commit 94ab7455abc213fc96760e29ab2e943ec682fb22 Author: Daniel Drake 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: Adam Jackson Signed-off-by: Daniel Drake commit a6c71ce5d2d2fe89e07a2ef5041c915acc3dc686 Author: Tiago Vignatti Date: Mon Mar 28 19:21:28 2011 +0300 os: fix memory and fd leaks in Popen Signed-off-by: Tiago Vignatti Reviewed-by: Peter Hutterer Reviewed-by: Nicolas Peninguy commit c9051b684b524549eab6d5b88ee3e195a6f6fbe8 Author: Alan Coopersmith Date: Wed Nov 5 18:25:57 2008 -0800 Use OsSignal in Popen/Pclose to avoid SysV signal() stupidity commit 0e9ef65fa583bf2393dd0fda82df6f092387b425 Author: Keith Packard Date: Wed Nov 7 16:33:10 2007 -0800 Don't frob timers unless SmartSchedule is running commit 2338d5c9914e2a43c3a4f7ee0f4355ad0a1ad9e7 Author: Arjan van de Ven 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: Keith Packard **Note**: The above change also required ABI changes in hw/nxagent/. commit abe0a51f3f790f8c055289465e130177c4b647cc Author: Ben Byer 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 Date: Wed Sep 12 13:23:13 2007 +0000 Fix build on FreeBSD after Popen changes. commit a5b8053606d6e786cdcf6734f271acc05f9cc588 Author: Adam Jackson 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: Mike Gabriel --- nx-X11/config/cf/Imake.tmpl | 9 +- nx-X11/programs/Xserver/Xext/shm.c | 5 +- nx-X11/programs/Xserver/Xext/xf86bigfont.c | 6 +- nx-X11/programs/Xserver/dix/dispatch.c | 16 ++- nx-X11/programs/Xserver/hw/nxagent/Display.c | 2 +- nx-X11/programs/Xserver/hw/nxagent/Display.h | 29 ++--- nx-X11/programs/Xserver/hw/nxagent/Handlers.c | 8 +- nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c | 9 +- nx-X11/programs/Xserver/include/dixstruct.h | 17 +-- nx-X11/programs/Xserver/os/WaitFor.c | 28 ++-- nx-X11/programs/Xserver/os/io.c | 13 +- nx-X11/programs/Xserver/os/osinit.c | 5 +- nx-X11/programs/Xserver/os/utils.c | 164 ++++++++++++++---------- 13 files changed, 159 insertions(+), 152 deletions(-) (limited to 'nx-X11/programs/Xserver/include') diff --git a/nx-X11/config/cf/Imake.tmpl b/nx-X11/config/cf/Imake.tmpl index d4b033888..944af2fdc 100644 --- a/nx-X11/config/cf/Imake.tmpl +++ b/nx-X11/config/cf/Imake.tmpl @@ -1289,6 +1289,12 @@ TCLIBDIR = TclLibDir #ifndef ToolkitStringsABIOptions #define ToolkitStringsABIOptions /**/ #endif +#ifndef HasSetitimer +#define HasSetitimer YES +#endif +#ifndef HasSetitimerDefines +#define HasSetitimerDefines -DHAVE_SETITIMER=1 +#endif #ifndef HasLdRunPath #define HasLdRunPath NO #endif @@ -1841,6 +1847,7 @@ MODLDCOMBINEFLAGS = ModuleLdCombineFlags STD_CPP_OPTIONS = StandardCppOptions STD_CPP_DEFINES = StandardCppOptions StandardCppDefines $(PROJECT_DEFINES) STD_DEFINES = StandardDefines $(PROJECT_DEFINES) +SETITIMER_DEFINES = HasSetitimerDefines EXTRA_LOAD_FLAGS = ExtraLoadFlags EXTRA_LDOPTIONS = ExtraLoadOptions EXTRA_LIBRARIES = MallocLibraries ExtraLibraries @@ -1966,7 +1973,7 @@ MODLDCOMBINEFLAGS = ModuleLdCombineFlags * LOCAL_LDFLAGS contains client-specific ld flags flags set in Imakefile */ ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(INSTALLED_INCLUDES) $(STD_INCLUDES) - ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(THREADS_DEFINES) $(MODULE_DEFINES) $(DEFINES) $(EXTRA_DEFINES) + ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(SETITIMER_DEFINES) $(PROTO_DEFINES) $(THREADS_DEFINES) $(MODULE_DEFINES) $(DEFINES) $(EXTRA_DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(THREADS_CFLAGS) $(MODULE_CFLAGS) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES) $(DEPEND_DEFINES) LDPRELIB = LdPreLib $(INSTALLED_LIBS) diff --git a/nx-X11/programs/Xserver/Xext/shm.c b/nx-X11/programs/Xserver/Xext/shm.c index 263adc3df..274284151 100644 --- a/nx-X11/programs/Xserver/Xext/shm.c +++ b/nx-X11/programs/Xserver/Xext/shm.c @@ -150,7 +150,6 @@ static ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage}; #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) -#include static Bool badSysCall = FALSE; @@ -167,7 +166,7 @@ static Bool CheckForShmSyscall() int shmid = -1; /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ - oldHandler = signal(SIGSYS, SigSysHandler); + oldHandler = OsSignal(SIGSYS, SigSysHandler); badSysCall = FALSE; shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); @@ -182,7 +181,7 @@ static Bool CheckForShmSyscall() /* Allocation failed */ badSysCall = TRUE; } - signal(SIGSYS, oldHandler); + OsSignal(SIGSYS, oldHandler); return(!badSysCall); } diff --git a/nx-X11/programs/Xserver/Xext/xf86bigfont.c b/nx-X11/programs/Xserver/Xext/xf86bigfont.c index 0ad411fc3..107b0f23f 100644 --- a/nx-X11/programs/Xserver/Xext/xf86bigfont.c +++ b/nx-X11/programs/Xserver/Xext/xf86bigfont.c @@ -106,8 +106,6 @@ static Bool badSysCall = FALSE; #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) -#include - static void SigSysHandler( int signo) @@ -122,7 +120,7 @@ CheckForShmSyscall(void) int shmid = -1; /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ - oldHandler = signal(SIGSYS, SigSysHandler); + oldHandler = OsSignal(SIGSYS, SigSysHandler); badSysCall = FALSE; shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); @@ -136,7 +134,7 @@ CheckForShmSyscall(void) /* Allocation failed */ badSysCall = TRUE; } - signal(SIGSYS, oldHandler); + OsSignal(SIGSYS, oldHandler); return (!badSysCall); } diff --git a/nx-X11/programs/Xserver/dix/dispatch.c b/nx-X11/programs/Xserver/dix/dispatch.c index 68c207e33..3869ef723 100644 --- a/nx-X11/programs/Xserver/dix/dispatch.c +++ b/nx-X11/programs/Xserver/dix/dispatch.c @@ -221,7 +221,11 @@ InitSelections() #define SMART_SCHEDULE_DEFAULT_INTERVAL 20 /* ms */ #define SMART_SCHEDULE_MAX_SLICE 200 /* ms */ -Bool SmartScheduleDisable = FALSE; +#ifdef HAVE_SETITIMER +#define SMART_SCHEDULE_DEFAULT_SIGNAL_ENABLE HAVE_SETITIMER +Bool SmartScheduleSignalEnable = SMART_SCHEDULE_DEFAULT_SIGNAL_ENABLE; +#endif + long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; @@ -351,7 +355,7 @@ Dispatch(void) nready = WaitForSomething(clientReady); - if (nready && !SmartScheduleDisable) + if (nready) { clientReady[0] = SmartScheduleClient (clientReady, nready); nready = 1; @@ -386,8 +390,7 @@ Dispatch(void) ProcessInputEvents(); FlushIfCriticalOutputPending(); } - if (!SmartScheduleDisable && - (SmartScheduleTime - start_tick) >= SmartScheduleSlice) + if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice) { /* Penalize clients which consume ticks */ if (client->smart_priority > SMART_MIN_PRIORITY) @@ -415,7 +418,10 @@ Dispatch(void) result = BadLength; else result = (* client->requestVector[MAJOROP])(client); - + + if (!SmartScheduleSignalEnable) + SmartScheduleTime = GetTimeInMillis(); + if (result != Success) { if (client->noClientException != Success) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Display.c b/nx-X11/programs/Xserver/hw/nxagent/Display.c index c683751f6..c764f50ae 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Display.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Display.c @@ -669,7 +669,7 @@ static void nxagentDisplayBlockHandler(Display *display, int reason) nxagentBlocking = 1; - if (SmartScheduleDisable == 1) + if (!SmartScheduleSignalEnable) { /* diff --git a/nx-X11/programs/Xserver/hw/nxagent/Display.h b/nx-X11/programs/Xserver/hw/nxagent/Display.h index 75da371d8..759b0de35 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Display.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Display.h @@ -116,36 +116,29 @@ Bool nxagentReconnectDisplay(void *p0); * Deal with the smart scheduler. */ +#if HAVE_SETITIMER #define nxagentInitTimer() \ \ SmartScheduleInit(); #define nxagentStopTimer() \ \ - if (SmartScheduleTimerStopped == 0) \ - { \ - SmartScheduleStopTimer(); \ - } \ -\ - SmartScheduleIdle = 1; + SmartScheduleStopTimer(); \ #define nxagentStartTimer() \ \ - if (SmartScheduleTimerStopped == 1) \ - { \ - SmartScheduleStartTimer(); \ - } \ -\ - SmartScheduleIdle = 0; + SmartScheduleStartTimer(); #define nxagentDisableTimer() \ \ - if (SmartScheduleTimerStopped == 0) \ - { \ - SmartScheduleStopTimer(); \ - } \ -\ - SmartScheduleDisable = 1; + SmartScheduleStopTimer(); \ + SmartScheduleSignalEnable = FALSE; +#else +#define nxagentInitTimer() +#define nxagentStopTimer() +#define nxagentStartTimer() +#define nxagentDisableTimer() +#endif /* HAVE_SETITIMER */ /* * File descriptor currently used by diff --git a/nx-X11/programs/Xserver/hw/nxagent/Handlers.c b/nx-X11/programs/Xserver/hw/nxagent/Handlers.c index 8e80a1524..634f7aafd 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Handlers.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Handlers.c @@ -597,7 +597,7 @@ void nxagentWakeupHandler(void * data, int count, void * mask) nxagentHandleConnectionStates(); } - if (SmartScheduleDisable == 1) + if (!SmartScheduleSignalEnable) { #ifdef DEBUG @@ -885,7 +885,7 @@ void nxagentShadowWakeupHandler(void * data, int count, void * mask) nxagentHandleConnectionStates(); } - if (SmartScheduleDisable == 1) + if (!SmartScheduleSignalEnable) { #ifdef DEBUG @@ -1075,7 +1075,7 @@ void nxagentDispatchHandler(ClientPtr client, int in, int out) #endif } - if (SmartScheduleDisable == 1) + if (!SmartScheduleSignalEnable) { /* @@ -1150,7 +1150,7 @@ void nxagentDispatchHandler(ClientPtr client, int in, int out) * the inner dispatch loop forever. */ - if (SmartScheduleDisable == 1) + if (!SmartScheduleSignalEnable) { if (client -> index != nxagentDispatch.client) diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c index 652d54479..5792a41c5 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c @@ -387,7 +387,7 @@ Reply Total Cached Bits In Bits Out Bits/Reply Ratio #endif - if (nready && !SmartScheduleDisable) + if (nready) { clientReady[0] = SmartScheduleClient (clientReady, nready); nready = 1; @@ -422,8 +422,7 @@ Reply Total Cached Bits In Bits Out Bits/Reply Ratio ProcessInputEvents(); FlushIfCriticalOutputPending(); } - if (!SmartScheduleDisable && - (SmartScheduleTime - start_tick) >= SmartScheduleSlice) + if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice) { /* Penalize clients which consume ticks */ if (client->smart_priority > SMART_MIN_PRIORITY) @@ -512,6 +511,10 @@ Reply Total Cached Bits In Bits Out Bits/Reply Ratio result = (* client->requestVector[MAJOROP])(client); #endif + + if (!SmartScheduleSignalEnable) + SmartScheduleTime = GetTimeInMillis(); + if (result != Success) { if (client->noClientException != Success) diff --git a/nx-X11/programs/Xserver/include/dixstruct.h b/nx-X11/programs/Xserver/include/dixstruct.h index 3c97e5bb7..1096f5c40 100644 --- a/nx-X11/programs/Xserver/include/dixstruct.h +++ b/nx-X11/programs/Xserver/include/dixstruct.h @@ -150,18 +150,19 @@ extern long SmartScheduleTime; extern long SmartScheduleInterval; extern long SmartScheduleSlice; extern long SmartScheduleMaxSlice; -extern unsigned long SmartScheduleIdleCount; -extern Bool SmartScheduleDisable; -extern Bool SmartScheduleIdle; -extern Bool SmartScheduleTimerStopped; -extern Bool SmartScheduleStartTimer(void); -#ifdef NXAGENT_SERVER -extern Bool SmartScheduleStopTimer(void); +#ifdef HAVE_SETITIMER +#if HAVE_SETITIMER +extern Bool SmartScheduleSignalEnable; +#else +#define SmartScheduleSignalEnable FALSE +#endif #endif +extern void SmartScheduleStartTimer(void); +extern void SmartScheduleStopTimer(void); #define SMART_MAX_PRIORITY (20) #define SMART_MIN_PRIORITY (-20) -extern Bool SmartScheduleInit(void); +extern void SmartScheduleInit(void); /* This prototype is used pervasively in Xext, dix */ #define DISPATCH_PROC(func) int func(ClientPtr /* client */) diff --git a/nx-X11/programs/Xserver/os/WaitFor.c b/nx-X11/programs/Xserver/os/WaitFor.c index 02c460f0c..4d7fe3f84 100644 --- a/nx-X11/programs/Xserver/os/WaitFor.c +++ b/nx-X11/programs/Xserver/os/WaitFor.c @@ -213,18 +213,10 @@ WaitForSomething(int *pClientsReady) ProcessWorkQueue(); if (XFD_ANYSET (&ClientsWithInput)) { - if (!SmartScheduleDisable) - { - someReady = TRUE; - waittime.tv_sec = 0; - waittime.tv_usec = 0; - wt = &waittime; - } - else - { - XFD_COPYSET (&ClientsWithInput, &clientsReadable); - break; - } + someReady = TRUE; + waittime.tv_sec = 0; + waittime.tv_usec = 0; + wt = &waittime; } if (someReady) { @@ -247,7 +239,8 @@ WaitForSomething(int *pClientsReady) } XFD_COPYSET(&AllSockets, &LastSelectMask); } - SmartScheduleIdle = TRUE; + SmartScheduleStopTimer (); + BlockHandler((void *)&wt, (void *)&LastSelectMask); if (NewOutputPending) FlushAllOutput(); @@ -387,13 +380,8 @@ WaitForSomething(int *pClientsReady) i = XTestProcessInputAction (i, &waittime); } #endif /* XTESTEXT1 */ - if (i >= 0) - { - SmartScheduleIdle = FALSE; - SmartScheduleIdleCount = 0; - if (SmartScheduleTimerStopped) - (void) SmartScheduleStartTimer (); - } + SmartScheduleStartTimer (); + if (i <= 0) /* An error or timeout occurred */ { #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) diff --git a/nx-X11/programs/Xserver/os/io.c b/nx-X11/programs/Xserver/os/io.c index 075eb677c..07399438e 100644 --- a/nx-X11/programs/Xserver/os/io.c +++ b/nx-X11/programs/Xserver/os/io.c @@ -465,24 +465,15 @@ ReadRequestFromClient(ClientPtr client) FD_SET(fd, &ClientsWithInput); else { - if (!SmartScheduleDisable) - FD_CLR(fd, &ClientsWithInput); - else - YieldControlNoInput(); + FD_CLR(fd, &ClientsWithInput); } } else { if (!gotnow) AvailableInput = oc; - if (!SmartScheduleDisable) - FD_CLR(fd, &ClientsWithInput); - else - YieldControlNoInput(); + FD_CLR(fd, &ClientsWithInput); } - if (SmartScheduleDisable) - if (++timesThisConnection >= MAX_TIMES_PER) - YieldControl(); #ifdef BIGREQS if (move_header) { diff --git a/nx-X11/programs/Xserver/os/osinit.c b/nx-X11/programs/Xserver/os/osinit.c index 08fbb8c89..a660337ca 100644 --- a/nx-X11/programs/Xserver/os/osinit.c +++ b/nx-X11/programs/Xserver/os/osinit.c @@ -217,9 +217,8 @@ OsInit(void) * log file name if logging to a file is desired. */ LogInit(NULL, NULL); - if (!SmartScheduleDisable) - if (!SmartScheduleInit ()) - SmartScheduleDisable = TRUE; + SmartScheduleInit(); + OsInitAllocator(); } diff --git a/nx-X11/programs/Xserver/os/utils.c b/nx-X11/programs/Xserver/os/utils.c index af793454f..25cbb1e87 100644 --- a/nx-X11/programs/Xserver/os/utils.c +++ b/nx-X11/programs/Xserver/os/utils.c @@ -290,7 +290,8 @@ OsSignal(sig, handler) sigaddset(&act.sa_mask, sig); act.sa_flags = 0; act.sa_handler = handler; - sigaction(sig, &act, &oact); + if (sigaction(sig, &act, &oact)) + perror("sigaction"); return oact.sa_handler; #endif } @@ -1026,10 +1027,12 @@ ProcessCommandLine(int argc, char *argv[]) i = skip - 1; } #endif +#if HAVE_SETITIMER else if ( strcmp( argv[i], "-dumbSched") == 0) { - SmartScheduleDisable = TRUE; + SmartScheduleSignalEnable = FALSE; } +#endif else if ( strcmp( argv[i], "-schedInterval") == 0) { if (++i < argc) @@ -1353,30 +1356,15 @@ XNFstrdup(const char *s) return ret; } -unsigned long SmartScheduleIdleCount; -Bool SmartScheduleIdle; -Bool SmartScheduleTimerStopped; - -#ifdef SIGVTALRM -#define SMART_SCHEDULE_POSSIBLE -#endif - -#ifdef SMART_SCHEDULE_POSSIBLE -#define SMART_SCHEDULE_SIGNAL SIGALRM -#define SMART_SCHEDULE_TIMER ITIMER_REAL -#endif - -#ifdef NX_TRANS_SOCKET void SmartScheduleStopTimer (void) -#else -static void -SmartScheduleStopTimer (void) -#endif { -#ifdef SMART_SCHEDULE_POSSIBLE +#if HAVE_SETITIMER struct itimerval timer; + if (!SmartScheduleSignalEnable) + return; + #ifdef NX_TRANS_TEST fprintf(stderr, "SmartScheduleStopTimer: Stopping timer.\n"); #endif @@ -1386,96 +1374,101 @@ SmartScheduleStopTimer (void) timer.it_value.tv_sec = 0; timer.it_value.tv_usec = 0; (void) setitimer (ITIMER_REAL, &timer, 0); - SmartScheduleTimerStopped = TRUE; #endif } -Bool +void SmartScheduleStartTimer (void) { -#ifdef SMART_SCHEDULE_POSSIBLE +#if HAVE_SETITIMER struct itimerval timer; - #ifdef NX_TRANS_SOCKET - - if (SmartScheduleDisable) - { - return FALSE; - } - - #endif + if (!SmartScheduleSignalEnable) + return; #ifdef NX_TRANS_TEST fprintf(stderr, "SmartScheduleStartTimer: Starting timer with [%ld] ms.\n", SmartScheduleInterval); #endif - SmartScheduleTimerStopped = FALSE; timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = SmartScheduleInterval * 1000; timer.it_value.tv_sec = 0; timer.it_value.tv_usec = SmartScheduleInterval * 1000; - return setitimer (ITIMER_REAL, &timer, 0) >= 0; + setitimer (ITIMER_REAL, &timer, 0); #endif - return FALSE; } -#ifdef SMART_SCHEDULE_POSSIBLE +#if HAVE_SETITIMER static void SmartScheduleTimer (int sig) { - int olderrno = errno; - SmartScheduleTime += SmartScheduleInterval; #ifdef NX_TRANS_TEST fprintf(stderr, "SmartScheduleTimer: Got timer with time [%ld] ms.\n", SmartScheduleTime); #endif - - if (SmartScheduleIdle) - { - SmartScheduleStopTimer (); - } - errno = olderrno; } -#endif -Bool -SmartScheduleInit (void) +int +SmartScheduleEnable (void) { -#ifdef SMART_SCHEDULE_POSSIBLE + int ret = 0; struct sigaction act; - if (SmartScheduleDisable) - return TRUE; - + if (!SmartScheduleSignalEnable) + return 0; + #ifdef NX_TRANS_TEST - fprintf(stderr, "SmartScheduleInit: Initializing the smart scheduler.\n"); + fprintf(stderr, "SmartScheduleEnable: Enabling the smart scheduler.\n"); #endif - bzero ((char *) &act, sizeof(struct sigaction)); + memset((char *) &act, 0, sizeof(struct sigaction)); /* Set up the timer signal function */ + act.sa_flags = SA_RESTART; act.sa_handler = SmartScheduleTimer; sigemptyset (&act.sa_mask); - sigaddset (&act.sa_mask, SMART_SCHEDULE_SIGNAL); - if (sigaction (SMART_SCHEDULE_SIGNAL, &act, 0) < 0) - { - perror ("sigaction for smart scheduler"); - return FALSE; - } - /* Set up the virtual timer */ - if (!SmartScheduleStartTimer ()) - { - perror ("scheduling timer"); - return FALSE; + sigaddset (&act.sa_mask, SIGALRM); + ret = sigaction(SIGALRM, &act, 0); + return ret; +} + +static int +SmartSchedulePause(void) +{ + int ret = 0; + struct sigaction act; + + if (!SmartScheduleSignalEnable) + return 0; + + #ifdef NX_TRANS_TEST + fprintf(stderr, "SmartSchedulePause: Pausing the smart scheduler.\n"); + #endif + + memset((char *) &act, 0, sizeof(struct sigaction)); + + act.sa_handler = SIG_IGN; + sigemptyset(&act.sa_mask); + ret = sigaction(SIGALRM, &act, 0); + return ret; +} +#endif + +void +SmartScheduleInit(void) +{ +#if HAVE_SETITIMER + #ifdef NX_TRANS_TEST + fprintf(stderr, "SmartScheduleInit: Initializing the smart scheduler.\n"); + #endif + + if (SmartScheduleEnable() < 0) { + perror("sigaction for smart scheduler"); + SmartScheduleSignalEnable = FALSE; } - /* stop the timer and wait for WaitForSomething to start it */ - SmartScheduleStopTimer (); - return TRUE; -#else - return FALSE; #endif } @@ -1558,7 +1551,11 @@ System(char *command) return(1); #ifdef SIGCHLD - csig = signal(SIGCHLD, SIG_DFL); + csig = OsSignal(SIGCHLD, SIG_DFL); + if (csig == SIG_ERR) { + perror("signal"); + return -1; + } #endif #ifdef DEBUG @@ -1596,7 +1593,10 @@ System(char *command) #endif #ifdef SIGCHLD - signal(SIGCHLD, csig); + if (OsSignal(SIGCHLD, csig) == SIG_ERR) { + perror("signal"); + return -1; + } #endif return p == -1 ? -1 : status; @@ -1629,6 +1629,17 @@ Popen(char *command, char *type) return NULL; } + /* Ignore the smart scheduler while this is going on */ +#if HAVE_SETITIMER + if (SmartSchedulePause() < 0) { + close(pdes[0]); + close(pdes[1]); + free(cur); + perror("signal"); + return NULL; + } +#endif + #ifdef NX_TRANS_EXIT if (OsVendorStartRedirectErrorFProc != NULL) { OsVendorStartRedirectErrorFProc(); @@ -1640,6 +1651,10 @@ Popen(char *command, char *type) close(pdes[0]); close(pdes[1]); free(cur); +#if HAVE_SETITIMER + if (SmartScheduleEnable() < 0) + perror("signal"); +#endif #ifdef NX_TRANS_EXIT if (OsVendorEndRedirectErrorFProc != NULL) { OsVendorEndRedirectErrorFProc(); @@ -1714,6 +1729,13 @@ Popen(char *command, char *type) OsReleaseSignals (); #endif +#if HAVE_SETITIMER + if (SmartScheduleEnable() < 0) { + perror("signal"); + return NULL; + } +#endif + execl("/bin/sh", "sh", "-c", command, (char *)NULL); _exit(127); } -- cgit v1.2.3 From 239fe3d0802b12ce8947741693244ff8154fa559 Mon Sep 17 00:00:00 2001 From: Rami Ylimäki Date: Wed, 15 Feb 2017 16:42:14 +0100 Subject: os: Add facilities for client ID tracking. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 6d6d4cb6043905d850834946e9bfc526ed5a9ef7 Author: Matthieu Herrb Date: Mon Jan 2 13:23:59 2012 +0000 Add OpenBSD support to DetermineClientCmd() Uses kvm_getargv() from libkvm. Signed-off-by: Matthieu Herrb Reviewed-by: Adam Jackson Signed-off-by: Keith Packard commit cfc4c3d7fa8bd4da4c08b2ab8e6f85435f75353a Author: Alan Coopersmith Date: Sat Dec 24 10:00:56 2011 -0800 Add Solaris support to DetermineClientCmd Uses /proc/pid/psinfo to read command & partial arguments. Moves cmdsize & argsize variables into non-Solaris #else clause to avoid unused variable warnings. Fixes format mismatch errors when building with DEBUG defined on a 64-bit platform (where Mask is defined as CARD32). Signed-off-by: Alan Coopersmith Reviewed-by: Rami Ylimäki Signed-off-by: Keith Packard commit 780133f9ae7fada462714b47e79d26075bbd9abe Author: Alan Coopersmith Date: Fri Oct 28 21:29:50 2011 -0700 Convert DetermineClientCmd to use strdup instead of malloc+strncpy *cmdname is initialized to NULL earlier in the function, so it's okay to overwrite it with NULL if strdup fails, don't need that extra check. Signed-off-by: Alan Coopersmith Reviewed-by: Jeremy Huddleston commit 2ef4ff45ef1fcfc4967ebe3d550408769e5f6500 Author: Erkki Seppälä Date: Fri Mar 25 10:38:23 2011 +0200 os/client: Prevent rare fd leak in DetermineClientPid DetermineClientPid didn't close file descriptor if read on /proc/pid/cmdline failed. Adjusted the code to disregard the close return value and perform the return after that, if the read failed or returned EOF. Signed-off-by: Mark Kettenis Signed-off-by: Erkki Seppälä Reviewed-by: Rami Ylimäki Signed-off-by: Keith Packard commit 1e933665bef26c74196bb7c59910e6a78bcacf0e Author: Rami Ylimäki Date: Wed Dec 22 16:51:09 2010 +0200 os: Add facilities for client ID tracking. An interface is provided for figuring out the PID and process name of a client. Make some existing functionality from SELinux and IA extensions available for general use. Signed-off-by: Rami Ylimäki Reviewed-by: Tiago Vignatti Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/Imakefile | 9 + nx-X11/programs/Xserver/dix/dispatch.c | 10 + nx-X11/programs/Xserver/dix/main.c | 3 + nx-X11/programs/Xserver/include/Imakefile | 1 + nx-X11/programs/Xserver/include/client.h | 60 +++++ nx-X11/programs/Xserver/include/dixstruct.h | 3 + nx-X11/programs/Xserver/os/Imakefile | 2 + nx-X11/programs/Xserver/os/client.c | 397 ++++++++++++++++++++++++++++ 8 files changed, 485 insertions(+) create mode 100644 nx-X11/programs/Xserver/include/client.h create mode 100644 nx-X11/programs/Xserver/os/client.c (limited to 'nx-X11/programs/Xserver/include') diff --git a/nx-X11/programs/Xserver/Imakefile b/nx-X11/programs/Xserver/Imakefile index 2af91821d..745b26154 100644 --- a/nx-X11/programs/Xserver/Imakefile +++ b/nx-X11/programs/Xserver/Imakefile @@ -323,6 +323,15 @@ NXAGENTNXLIBS = -L../../../nxcomp \ -lXcompshad \ -lXrender -lXfixes -lXfont -lXcomposite -lXdmcp \ -lNX_X11 -lXext +#elif defined(OpenBSDArchitecture) +NXAGENTNXLIBS = -L../../../nxcomp \ + -L../../../nx-X11/exports/lib \ + -L../../../nxcompshad \ + -lkvm \ + -lXcomp \ + -lXcompshad \ + -lXrender -lXfixes -lXfont -lXcomposite -lXinerama -lXdmcp \ + -lNX_X11 -lXext #else NXAGENTNXLIBS = -L../../../nxcomp \ -L../../../nx-X11/exports/lib \ diff --git a/nx-X11/programs/Xserver/dix/dispatch.c b/nx-X11/programs/Xserver/dix/dispatch.c index 3869ef723..16b94301f 100644 --- a/nx-X11/programs/Xserver/dix/dispatch.c +++ b/nx-X11/programs/Xserver/dix/dispatch.c @@ -112,6 +112,7 @@ int ProcInitialConnection(); #include "inputstr.h" #include "xkbsrv.h" #endif +#include "client.h" #define mskcnt ((MAXCLIENTS + 31) / 32) #define BITMASK(i) (1U << ((i) & 31)) @@ -3560,6 +3561,9 @@ CloseDownClient(register ClientPtr client) CallCallbacks((&ClientStateCallback), (void *)&clientinfo); } FreeClientResources(client); + /* Disable client ID tracking. This must be done after + * ClientStateCallback. */ + ReleaseClientIds(client); if (client->index < nextFreeClientID) nextFreeClientID = client->index; clients[client->index] = NullClient; @@ -3643,6 +3647,7 @@ void InitClient(ClientPtr client, int i, void * ospriv) client->smart_start_tick = SmartScheduleTime; client->smart_stop_tick = SmartScheduleTime; client->smart_check_tick = SmartScheduleTime; + client->clientIds = NULL; } extern int clientPrivateLen; @@ -3724,6 +3729,11 @@ ClientPtr NextAvailableClient(void * ospriv) currentMaxClients++; while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) nextFreeClientID++; + + /* Enable client ID tracking. This must be done before + * ClientStateCallback. */ + ReserveClientIds(client); + if (ClientStateCallback) { NewClientInfoRec clientinfo; diff --git a/nx-X11/programs/Xserver/dix/main.c b/nx-X11/programs/Xserver/dix/main.c index 7bd41d865..50bbeb3dc 100644 --- a/nx-X11/programs/Xserver/dix/main.c +++ b/nx-X11/programs/Xserver/dix/main.c @@ -100,6 +100,7 @@ Equipment Corporation. #include "site.h" #include "dixfont.h" #include "extnsionst.h" +#include "client.h" #ifdef PANORAMIX #include "panoramiXsrv.h" #else @@ -382,6 +383,7 @@ main(int argc, char *argv[], char *envp[]) InitInput(argc, argv); if (InitAndStartDevices() != Success) FatalError("failed to initialize core devices"); + ReserveClientIds(serverClient); InitFonts(); if (loadableFonts) { @@ -470,6 +472,7 @@ main(int argc, char *argv[], char *envp[]) #endif FreeAuditTimer(); + ReleaseClientIds(serverClient); free(serverClient->devPrivates); serverClient->devPrivates = NULL; diff --git a/nx-X11/programs/Xserver/include/Imakefile b/nx-X11/programs/Xserver/include/Imakefile index d1d7bd651..53f193ec8 100644 --- a/nx-X11/programs/Xserver/include/Imakefile +++ b/nx-X11/programs/Xserver/include/Imakefile @@ -16,6 +16,7 @@ depend:: InstallDriverSDKNonExecFile(XIstubs.h,$(DRIVERSDKINCLUDEDIR)) InstallDriverSDKNonExecFile(bstore.h,$(DRIVERSDKINCLUDEDIR)) InstallDriverSDKNonExecFile(bstorestr.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(client.h,$(DRIVERSDKINCLUDEDIR)) InstallDriverSDKNonExecFile(colormap.h,$(DRIVERSDKINCLUDEDIR)) InstallDriverSDKNonExecFile(colormapst.h,$(DRIVERSDKINCLUDEDIR)) InstallDriverSDKNonExecFile(cursor.h,$(DRIVERSDKINCLUDEDIR)) diff --git a/nx-X11/programs/Xserver/include/client.h b/nx-X11/programs/Xserver/include/client.h new file mode 100644 index 000000000..87f2b1172 --- /dev/null +++ b/nx-X11/programs/Xserver/include/client.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All + * rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 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 + * AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +/* Author: Rami Ylimäki */ + +#ifndef CLIENT_H +#define CLIENT_H + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif /* HAVE_DIX_CONFIG_H */ +#include +#include + +/* Client IDs. Use GetClientPid, GetClientCmdName and GetClientCmdArgs + * instead of accessing the fields directly. */ +typedef struct { + pid_t pid; /* process ID, -1 if not available */ + const char *cmdname; /* process name, NULL if not available */ + const char *cmdargs; /* process arguments, NULL if not available */ +} ClientIdRec, *ClientIdPtr; + +struct _Client; + +/* Initialize and clean up. */ +void ReserveClientIds(struct _Client *client); +void ReleaseClientIds(struct _Client *client); + +/* Determine client IDs for caching. Exported on purpose for + * extensions such as SELinux. */ +extern _X_EXPORT pid_t DetermineClientPid(struct _Client *client); +extern _X_EXPORT void DetermineClientCmd(pid_t, const char **cmdname, + const char **cmdargs); + +/* Query cached client IDs. Exported on purpose for drivers. */ +extern _X_EXPORT pid_t GetClientPid(struct _Client *client); +extern _X_EXPORT const char *GetClientCmdName(struct _Client *client); +extern _X_EXPORT const char *GetClientCmdArgs(struct _Client *client); + +#endif /* CLIENT_H */ diff --git a/nx-X11/programs/Xserver/include/dixstruct.h b/nx-X11/programs/Xserver/include/dixstruct.h index 1096f5c40..b8ee8e9cf 100644 --- a/nx-X11/programs/Xserver/include/dixstruct.h +++ b/nx-X11/programs/Xserver/include/dixstruct.h @@ -24,6 +24,7 @@ SOFTWARE. #ifndef DIXSTRUCT_H #define DIXSTRUCT_H +#include "client.h" #include "dix.h" #include "resource.h" #include "cursor.h" @@ -141,6 +142,8 @@ typedef struct _Client { long smart_start_tick; long smart_stop_tick; long smart_check_tick; + + ClientIdPtr clientIds; } ClientRec; /* diff --git a/nx-X11/programs/Xserver/os/Imakefile b/nx-X11/programs/Xserver/os/Imakefile index 144cb5a55..86f5cd4e6 100644 --- a/nx-X11/programs/Xserver/os/Imakefile +++ b/nx-X11/programs/Xserver/os/Imakefile @@ -128,6 +128,7 @@ TMEMCMP_OBJS = timingsafe_memcmp.o BOOTSTRAPCFLAGS = SRCS = WaitFor.c \ access.c \ + client.c \ connection.c \ io.c \ $(COLOR_SRCS) \ @@ -151,6 +152,7 @@ BOOTSTRAPCFLAGS = OBJS = WaitFor.o \ access.o \ + client.o \ connection.o \ io.o \ $(COLOR_OBJS) \ diff --git a/nx-X11/programs/Xserver/os/client.c b/nx-X11/programs/Xserver/os/client.c new file mode 100644 index 000000000..ef5e3935d --- /dev/null +++ b/nx-X11/programs/Xserver/os/client.c @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All + * rights reserved. + * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 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 + * AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +/** + * @file + * + * This file contains functionality for identifying clients by various + * means. The primary purpose of identification is to simply aid in + * finding out which clients are using X server and how they are using + * it. For example, it's often necessary to monitor what requests + * clients are executing (to spot bad behaviour) and how they are + * allocating resources in X server (to spot excessive resource + * usage). + * + * This framework automatically allocates information, that can be + * used for client identification, when a client connects to the + * server. The information is freed when the client disconnects. The + * allocated information is just a collection of various IDs, such as + * PID and process name for local clients, that are likely to be + * useful in analyzing X server usage. + * + * Users of the framework can query ID information about clients at + * any time. To avoid repeated polling of IDs the users can also + * subscribe for notifications about the availability of ID + * information. IDs have been allocated before ClientStateCallback is + * called with ClientStateInitial state. Similarly the IDs will be + * released after ClientStateCallback is called with ClientStateGone + * state. + * + * Author: Rami Ylimäki + */ + +#include +#include +#include + +#include "client.h" +#include "os.h" +#include "dixstruct.h" + +#ifdef __sun +#include +#include +#endif + +#ifdef __OpenBSD__ +#include +#include +#include + +#include +#include +#endif + +/** + * Try to determine a PID for a client from its connection + * information. This should be called only once when new client has + * connected, use GetClientPid to determine the PID at other times. + * + * @param[in] client Connection linked to some process. + * + * @return PID of the client. Error (-1) if PID can't be determined + * for the client. + * + * @see GetClientPid + */ +pid_t +DetermineClientPid(struct _Client * client) +{ + LocalClientCredRec *lcc = NULL; + pid_t pid = -1; + + if (client == NullClient) + return pid; + + if (client == serverClient) + return getpid(); + + if (GetLocalClientCreds(client, &lcc) != -1) { + if (lcc->fieldsSet & LCC_PID_SET) + pid = lcc->pid; + FreeLocalClientCreds(lcc); + } + + return pid; +} + +/** + * Try to determine a command line string for a client based on its + * PID. Note that mapping PID to a command hasn't been implemented for + * some operating systems. This should be called only once when a new + * client has connected, use GetClientCmdName/Args to determine the + * string at other times. + * + * @param[in] pid Process ID of a client. + + * @param[out] cmdname Client process name without arguments. You must + * release this by calling free. On error NULL is + * returned. Pass NULL if you aren't interested in + * this value. + * @param[out] cmdargs Arguments to client process. Useful for + * identifying a client that is executed from a + * launcher program. You must release this by + * calling free. On error NULL is returned. Pass + * NULL if you aren't interested in this value. + * + * @see GetClientCmdName/Args + */ +void +DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs) +{ + char path[PATH_MAX + 1]; + int totsize = 0; + int fd = 0; + + if (cmdname) + *cmdname = NULL; + if (cmdargs) + *cmdargs = NULL; + + if (pid == -1) + return; + +#ifdef __sun /* Solaris */ + /* Solaris does not support /proc/pid/cmdline, but makes information + * similar to what ps shows available in a binary structure in the + * /proc/pid/psinfo file. */ + if (snprintf(path, sizeof(path), "/proc/%d/psinfo", pid) < 0) + return; + fd = open(path, O_RDONLY); + if (fd < 0) { + ErrorF("Failed to open %s: %s\n", path, strerror(errno)); + return; + } + else { + psinfo_t psinfo = { 0 }; + char *sp; + + totsize = read(fd, &psinfo, sizeof(psinfo_t)); + close(fd); + if (totsize <= 0) + return; + + /* pr_psargs is the first PRARGSZ (80) characters of the command + * line string - assume up to the first space is the command name, + * since it's not delimited. While there is also pr_fname, that's + * more limited, giving only the first 16 chars of the basename of + * the file that was exec'ed, thus cutting off many long gnome + * command names, or returning "isapython2.6" for all python scripts. + */ + psinfo.pr_psargs[PRARGSZ - 1] = '\0'; + sp = strchr(psinfo.pr_psargs, ' '); + if (sp) + *sp++ = '\0'; + + if (cmdname) + *cmdname = strdup(psinfo.pr_psargs); + + if (cmdargs && sp) + *cmdargs = strdup(sp); + } +#elif defined(__OpenBSD__) + /* on OpenBSD use kvm_getargv() */ + { + kvm_t *kd; + char errbuf[_POSIX2_LINE_MAX]; + char **argv; + struct kinfo_proc *kp; + size_t len = 0; + int i, n; + + kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, errbuf); + if (kd == NULL) + return; + kp = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), + &n); + if (n != 1) + return; + argv = kvm_getargv(kd, kp, 0); + *cmdname = strdup(argv[0]); + i = 1; + while (argv[i] != NULL) { + len += strlen(argv[i]) + 1; + i++; + } + *cmdargs = calloc(1, len); + i = 1; + while (argv[i] != NULL) { + strlcat(*cmdargs, argv[i], len); + strlcat(*cmdargs, " ", len); + i++; + } + kvm_close(kd); + } +#else /* Linux using /proc/pid/cmdline */ + + /* Check if /proc/pid/cmdline exists. It's not supported on all + * operating systems. */ + if (snprintf(path, sizeof(path), "/proc/%d/cmdline", pid) < 0) + return; + fd = open(path, O_RDONLY); + if (fd < 0) + return; + + /* Read the contents of /proc/pid/cmdline. It should contain the + * process name and arguments. */ + totsize = read(fd, path, sizeof(path)); + close(fd); + if (totsize <= 0) + return; + path[totsize - 1] = '\0'; + + /* Contruct the process name without arguments. */ + if (cmdname) { + *cmdname = strdup(path); + } + + /* Construct the arguments for client process. */ + if (cmdargs) { + int cmdsize = strlen(path) + 1; + int argsize = totsize - cmdsize; + char *args = NULL; + + if (argsize > 0) + args = malloc(argsize); + if (args) { + int i = 0; + + for (i = 0; i < (argsize - 1); ++i) { + const char c = path[cmdsize + i]; + + args[i] = (c == '\0') ? ' ' : c; + } + args[argsize - 1] = '\0'; + *cmdargs = args; + } + } +#endif +} + +/** + * Called when a new client connects. Allocates client ID information. + * + * @param[in] client Recently connected client. + */ +void +ReserveClientIds(struct _Client *client) +{ +#ifdef CLIENTIDS + if (client == NullClient) + return; + + assert(!client->clientIds); + client->clientIds = calloc(1, sizeof(ClientIdRec)); + if (!client->clientIds) + return; + + client->clientIds->pid = DetermineClientPid(client); + if (client->clientIds->pid != -1) + DetermineClientCmd(client->clientIds->pid, &client->clientIds->cmdname, + &client->clientIds->cmdargs); + + DebugF("client(%lx): Reserved pid(%d).\n", + (unsigned long) client->clientAsMask, client->clientIds->pid); + DebugF("client(%lx): Reserved cmdname(%s) and cmdargs(%s).\n", + (unsigned long) client->clientAsMask, + client->clientIds->cmdname ? client->clientIds->cmdname : "NULL", + client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL"); +#endif /* CLIENTIDS */ +} + +/** + * Called when an existing client disconnects. Frees client ID + * information. + * + * @param[in] client Recently disconnected client. + */ +void +ReleaseClientIds(struct _Client *client) +{ +#ifdef CLIENTIDS + if (client == NullClient) + return; + + if (!client->clientIds) + return; + + DebugF("client(%lx): Released pid(%d).\n", + (unsigned long) client->clientAsMask, client->clientIds->pid); + DebugF("client(%lx): Released cmdline(%s) and cmdargs(%s).\n", + (unsigned long) client->clientAsMask, + client->clientIds->cmdname ? client->clientIds->cmdname : "NULL", + client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL"); + + free((void *) client->clientIds->cmdname); /* const char * */ + free((void *) client->clientIds->cmdargs); /* const char * */ + free(client->clientIds); + client->clientIds = NULL; +#endif /* CLIENTIDS */ +} + +/** + * Get cached PID of a client. + * + * param[in] client Client whose PID has been already cached. + * + * @return Cached client PID. Error (-1) if called: + * - before ClientStateInitial client state notification + * - after ClientStateGone client state notification + * - for remote clients + * + * @see DetermineClientPid + */ +pid_t +GetClientPid(struct _Client *client) +{ + if (client == NullClient) + return -1; + + if (!client->clientIds) + return -1; + + return client->clientIds->pid; +} + +/** + * Get cached command name string of a client. + * + * param[in] client Client whose command line string has been already + * cached. + * + * @return Cached client command name. Error (NULL) if called: + * - before ClientStateInitial client state notification + * - after ClientStateGone client state notification + * - for remote clients + * - on OS that doesn't support mapping of PID to command line + * + * @see DetermineClientCmd + */ +const char * +GetClientCmdName(struct _Client *client) +{ + if (client == NullClient) + return NULL; + + if (!client->clientIds) + return NULL; + + return client->clientIds->cmdname; +} + +/** + * Get cached command arguments string of a client. + * + * param[in] client Client whose command line string has been already + * cached. + * + * @return Cached client command arguments. Error (NULL) if called: + * - before ClientStateInitial client state notification + * - after ClientStateGone client state notification + * - for remote clients + * - on OS that doesn't support mapping of PID to command line + * + * @see DetermineClientCmd + */ +const char * +GetClientCmdArgs(struct _Client *client) +{ + if (client == NullClient) + return NULL; + + if (!client->clientIds) + return NULL; + + return client->clientIds->cmdargs; +} -- cgit v1.2.3 From ed52cb2952bebf6b98e187ff1f8609690fae3d59 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 16 Feb 2017 10:51:40 +0000 Subject: dix: Pull client-is-local flag up to the ClientRec Backported from X.org commit ff8e3ad8074cd2c8bed49b39c40c2b4892118270 Author: Adam Jackson Date: Thu Sep 20 13:16:59 2012 -0400 dix: Pull client-is-local flag up to the ClientRec Reviewed-by: Daniel Stone Signed-off-by: Adam Jackson Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/Xext/xf86bigfont.c | 4 ++-- nx-X11/programs/Xserver/include/dixstruct.h | 1 + nx-X11/programs/Xserver/include/os.h | 2 -- nx-X11/programs/Xserver/os/access.c | 9 +-------- nx-X11/programs/Xserver/os/connection.c | 2 +- nx-X11/programs/Xserver/os/osdep.h | 1 - 6 files changed, 5 insertions(+), 14 deletions(-) (limited to 'nx-X11/programs/Xserver/include') diff --git a/nx-X11/programs/Xserver/Xext/xf86bigfont.c b/nx-X11/programs/Xserver/Xext/xf86bigfont.c index 107b0f23f..4c8f02c2c 100644 --- a/nx-X11/programs/Xserver/Xext/xf86bigfont.c +++ b/nx-X11/programs/Xserver/Xext/xf86bigfont.c @@ -366,7 +366,7 @@ ProcXF86BigfontQueryVersion( #endif reply.capabilities = #ifdef HAS_SHM - (LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0) + (client->local && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0) #else 0 #endif @@ -430,7 +430,7 @@ ProcXF86BigfontQueryFont( #else switch (client->req_len) { case 2: /* client with version 1.0 libX11 */ - stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0); + stuff_flags = (client->local && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0); break; case 3: /* client with version 1.1 libX11 */ stuff_flags = stuff->flags; diff --git a/nx-X11/programs/Xserver/include/dixstruct.h b/nx-X11/programs/Xserver/include/dixstruct.h index b8ee8e9cf..cdd2543a6 100644 --- a/nx-X11/programs/Xserver/include/dixstruct.h +++ b/nx-X11/programs/Xserver/include/dixstruct.h @@ -95,6 +95,7 @@ typedef struct _Client { void *requestBuffer; void *osPrivate; /* for OS layer, including scheduler */ Bool swapped; + Bool local; ReplySwapPtr pSwapReplyFunc; XID errorValue; int sequence; diff --git a/nx-X11/programs/Xserver/include/os.h b/nx-X11/programs/Xserver/include/os.h index af84f54c0..5de8463e7 100644 --- a/nx-X11/programs/Xserver/include/os.h +++ b/nx-X11/programs/Xserver/include/os.h @@ -317,8 +317,6 @@ typedef struct sockaddr * sockaddrPtr; extern int InvalidHost(sockaddrPtr /*saddr*/, int /*len*/, ClientPtr client); -extern int LocalClient(ClientPtr /* client */); - extern int LocalClientCred(ClientPtr, int *, int *); #define LCC_UID_SET (1 << 0) diff --git a/nx-X11/programs/Xserver/os/access.c b/nx-X11/programs/Xserver/os/access.c index e9d5d8ae8..d8d035ade 100644 --- a/nx-X11/programs/Xserver/os/access.c +++ b/nx-X11/programs/Xserver/os/access.c @@ -1264,13 +1264,6 @@ ComputeLocalClient(ClientPtr client) return FALSE; } -Bool LocalClient(ClientPtr client) -{ - if (!client->osPrivate) - return FALSE; - return ((OsCommPtr)client->osPrivate)->local_client; -} - /* * Return the uid and gid of a connected local client * @@ -1419,7 +1412,7 @@ AuthorizedClient(ClientPtr client) { if (!client || defeatAccessControl) return TRUE; - return LocalClient(client); + return client->local ? Success : BadAccess; } /* Add a host to the access control list. This is the external interface diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c index cee621384..917f79fa6 100644 --- a/nx-X11/programs/Xserver/os/connection.c +++ b/nx-X11/programs/Xserver/os/connection.c @@ -754,7 +754,7 @@ AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time) free (oc); return NullClient; } - oc->local_client = ComputeLocalClient(client); + client->local = ComputeLocalClient(client); { #if !defined(WIN32) ConnectionTranslation[fd] = client->index; diff --git a/nx-X11/programs/Xserver/os/osdep.h b/nx-X11/programs/Xserver/os/osdep.h index 709f33943..fdd8c7174 100644 --- a/nx-X11/programs/Xserver/os/osdep.h +++ b/nx-X11/programs/Xserver/os/osdep.h @@ -176,7 +176,6 @@ typedef struct _osComm { XID auth_id; /* authorization id */ CARD32 conn_time; /* timestamp if not established, else 0 */ struct _XtransConnInfo *trans_conn; /* transport connection object */ - Bool local_client; } OsCommRec, *OsCommPtr; extern int FlushClient( -- cgit v1.2.3 From f5301dee4e400698f5b8ea324686b8daba75152d Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Wed, 15 Mar 2017 12:08:46 +0100 Subject: Move SIGUSR1 notification as late as possible. commit f01e149d1af14ef9ee0e8a6743ab6a08f3bb677c Author: Adam Jackson Date: Thu Nov 1 15:41:11 2007 -0400 Move SIGUSR1 notification as late as possible. If we inherited a signal mask from the parent process that ignores SIGUSR1, then we will send SIGUSR1 to the parent to indicate when we're ready to accept connections. Unfortunately, we send this notification way too early, right after creating the sockets rather than just before entering the main loop. Move it to just before Dispatch() so we're not lying quite so much. Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/dix/main.c | 2 + nx-X11/programs/Xserver/include/os.h | 2 + nx-X11/programs/Xserver/os/connection.c | 87 +++++++++++++++++++-------------- 3 files changed, 53 insertions(+), 38 deletions(-) (limited to 'nx-X11/programs/Xserver/include') diff --git a/nx-X11/programs/Xserver/dix/main.c b/nx-X11/programs/Xserver/dix/main.c index 50bbeb3dc..72ed40108 100644 --- a/nx-X11/programs/Xserver/dix/main.c +++ b/nx-X11/programs/Xserver/dix/main.c @@ -432,6 +432,8 @@ main(int argc, char *argv[], char *envp[]) FatalError("could not create connection block info"); } + NotifyParentProcess(); + Dispatch(); /* Now free up whatever must be freed */ diff --git a/nx-X11/programs/Xserver/include/os.h b/nx-X11/programs/Xserver/include/os.h index 5de8463e7..5dd5e2012 100644 --- a/nx-X11/programs/Xserver/include/os.h +++ b/nx-X11/programs/Xserver/include/os.h @@ -120,6 +120,8 @@ extern void ResetOsBuffers(void); extern void InitConnectionLimits(void); +extern void NotifyParentProcess(void); + extern void CreateWellKnownSockets(void); extern void ResetWellKnownSockets(void); diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c index d4627e97c..172ed6f4c 100644 --- a/nx-X11/programs/Xserver/os/connection.c +++ b/nx-X11/programs/Xserver/os/connection.c @@ -319,6 +319,52 @@ InitConnectionLimits(void) #endif } +/* + * If SIGUSR1 was set to SIG_IGN when the server started, assume that either + * + * a- The parent process is ignoring SIGUSR1 + * + * or + * + * b- The parent process is expecting a SIGUSR1 + * when the server is ready to accept connections + * + * In the first case, the signal will be harmless, in the second case, + * the signal will be quite useful. + */ +static void +InitParentProcess(void) +{ +#if !defined(WIN32) + OsSigHandlerPtr handler; + handler = OsSignal (SIGUSR1, SIG_IGN); + if ( handler == SIG_IGN) + RunFromSmartParent = TRUE; + OsSignal(SIGUSR1, handler); + ParentProcess = getppid (); +#ifdef __UNIXOS2__ + /* + * fg030505: under OS/2, xinit is not the parent process but + * the "grant parent" process of the server because execvpe() + * presents us an additional process number; + * GetPPID(pid) is part of libemxfix + */ + ParentProcess = GetPPID (ParentProcess); +#endif /* __UNIXOS2__ */ +#endif +} + +void +NotifyParentProcess(void) +{ +#if !defined(WIN32) + if (RunFromSmartParent) { + if (ParentProcess > 1) { + kill (ParentProcess, SIGUSR1); + } + } +#endif +} /***************** * CreateWellKnownSockets @@ -331,7 +377,6 @@ CreateWellKnownSockets(void) int i; int partial; char port[20]; - OsSigHandlerPtr handler; FD_ZERO(&AllSockets); FD_ZERO(&AllClients); @@ -385,33 +430,9 @@ CreateWellKnownSockets(void) OsSignal (SIGTERM, GiveUp); XFD_COPYSET (&WellKnownConnections, &AllSockets); ResetHosts(display); - /* - * Magic: If SIGUSR1 was set to SIG_IGN when - * the server started, assume that either - * - * a- The parent process is ignoring SIGUSR1 - * - * or - * - * b- The parent process is expecting a SIGUSR1 - * when the server is ready to accept connections - * - * In the first case, the signal will be harmless, - * in the second case, the signal will be quite - * useful - */ -#if !defined(WIN32) - handler = OsSignal (SIGUSR1, SIG_IGN); - if ( handler == SIG_IGN) - RunFromSmartParent = TRUE; - OsSignal(SIGUSR1, handler); - ParentProcess = getppid (); - if (RunFromSmartParent) { - if (ParentProcess > 1) { - kill (ParentProcess, SIGUSR1); - } - } -#endif + + InitParentProcess(); + #ifdef XDMCP XdmcpInit (); #endif @@ -499,16 +520,6 @@ ResetWellKnownSockets (void) ResetAuthorization (); ResetHosts(display); - /* - * See above in CreateWellKnownSockets about SIGUSR1 - */ -#if !defined(WIN32) - if (RunFromSmartParent) { - if (ParentProcess > 1) { - kill (ParentProcess, SIGUSR1); - } - } -#endif /* * restart XDMCP */ -- cgit v1.2.3 From 89496d987dc6a21250c9fdda2cd3668516061f5c Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Wed, 15 Mar 2017 14:10:24 +0000 Subject: os: Add -displayfd option commit 88bacc49f06da5927f716869f5a32672a8297ed0 Author: Chase Douglas Date: Wed Apr 4 15:29:42 2012 -0700 os: Add -displayfd option This option specifies a file descriptor in the launching process. X will scan for an available display number and write that number back to the launching process, at the same time as SIGUSR1 generation. This means display managers don't need to guess at available display numbers. As a consequence, if X fails to start when using -displayfd, it's not because the display was in use, so there's no point in retrying the X launch on a higher display number. Signed-off-by: Adam Jackson Signed-off-by: Chase Douglas Reviewed-by: Julien Cristau Tested-by: Julien Cristau Reviewed-by: Alan Coopersmith Signed-off-by: Peter Hutterer Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/dix/globals.c | 1 + nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 | 7 +++ nx-X11/programs/Xserver/include/opaque.h | 1 + nx-X11/programs/Xserver/os/connection.c | 76 ++++++++++++++++-------- nx-X11/programs/Xserver/os/utils.c | 10 ++++ 5 files changed, 69 insertions(+), 26 deletions(-) (limited to 'nx-X11/programs/Xserver/include') diff --git a/nx-X11/programs/Xserver/dix/globals.c b/nx-X11/programs/Xserver/dix/globals.c index a0af50fa8..5a3e22c26 100644 --- a/nx-X11/programs/Xserver/dix/globals.c +++ b/nx-X11/programs/Xserver/dix/globals.c @@ -149,6 +149,7 @@ int defaultColorVisualClass = -1; int monitorResolution = 0; char *display; +int displayfd; CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND; int argcGlobal; diff --git a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 index af5fc88f8..66f25b438 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 +++ b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 @@ -178,6 +178,13 @@ different from the user's real uid. .B \-core causes the server to generate a core dump on fatal errors. .TP 8 +.B \-displayfd \fIfd\fP +specifies a file descriptor in the launching process. Rather than specify +a display number, the X server will attempt to listen on successively higher +display numbers, and upon finding a free one, will write the port number back +on this file descriptor as a newline-terminated string. The \-pn option is +ignored when using \-displayfd. +.TP 8 .B \-deferglyphs \fIwhichfonts\fP specifies the types of fonts for which the server should attempt to use deferred glyph loading. \fIwhichfonts\fP can be all (all fonts), diff --git a/nx-X11/programs/Xserver/include/opaque.h b/nx-X11/programs/Xserver/include/opaque.h index bd286ba12..8f98bf1be 100644 --- a/nx-X11/programs/Xserver/include/opaque.h +++ b/nx-X11/programs/Xserver/include/opaque.h @@ -52,6 +52,7 @@ extern int defaultScreenSaverAllowExposures; extern int argcGlobal; extern char **argvGlobal; extern char *display; +extern int displayfd; extern int defaultBackingStore; extern Bool disableBackingStore; diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c index 2fa8ad12d..6dc0ff64d 100644 --- a/nx-X11/programs/Xserver/os/connection.c +++ b/nx-X11/programs/Xserver/os/connection.c @@ -138,6 +138,7 @@ int NumNotifyWriteFd; /* Number of NotifyFd members with write set */ Bool NewOutputPending; /* not yet attempted to write some new output */ Bool AnyWritesPending; /* true if some client blocked on write or NotifyFd with write */ Bool RunFromSmartParent; /* send SIGUSR1 to parent process */ +static char dynamic_display[7]; /* display name */ Bool PartialNetwork; /* continue even if unable to bind all addrs */ static Pid_t ParentProcess; @@ -359,6 +360,10 @@ void NotifyParentProcess(void) { #if !defined(WIN32) + if (dynamic_display[0]) { + write(displayfd, dynamic_display, strlen(dynamic_display)); + close(displayfd); + } if (RunFromSmartParent) { if (ParentProcess > 1) { kill (ParentProcess, SIGUSR1); @@ -367,6 +372,18 @@ NotifyParentProcess(void) #endif } +static Bool +TryCreateSocket(int num, int *partial) +{ + char port[20]; + + snprintf(port, sizeof(port), "%d", num); + + return (_XSERVTransMakeAllCOTSServerListeners(port, partial, + &ListenTransCount, + &ListenTransConns) >= 0); +} + /***************** * CreateWellKnownSockets * At initialization, create the sockets to listen on for new clients. @@ -377,7 +394,6 @@ CreateWellKnownSockets(void) { int i; int partial; - char port[20]; FD_ZERO(&AllSockets); FD_ZERO(&AllClients); @@ -392,33 +408,41 @@ CreateWellKnownSockets(void) FD_ZERO (&WellKnownConnections); - sprintf (port, "%d", atoi (display)); - - if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial, - &ListenTransCount, &ListenTransConns) >= 0) && - (ListenTransCount >= 1)) - { - if (!PartialNetwork && partial) - { - FatalError ("Failed to establish all listening sockets"); - } - else - { - ListenTransFds = (int *) malloc (ListenTransCount * sizeof (int)); - - for (i = 0; i < ListenTransCount; i++) - { - int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); - - ListenTransFds[i] = fd; - FD_SET (fd, &WellKnownConnections); - - if (!_XSERVTransIsLocal (ListenTransConns[i])) - { - DefineSelf (fd); - } + /* display is initialized to "0" by main(). It is then set to the display + * number if specified on the command line, or to NULL when the -displayfd + * option is used. */ + if (display) { + if (TryCreateSocket(atoi(display), &partial) && + ListenTransCount >= 1) + if (!PartialNetwork && partial) + FatalError ("Failed to establish all listening sockets"); + } + else { /* -displayfd */ + Bool found = 0; + for (i = 0; i < 65535 - X_TCP_PORT; i++) { + if (TryCreateSocket(i, &partial) && !partial) { + found = 1; + break; } + else + CloseWellKnownConnections(); } + if (!found) + FatalError("Failed to find a socket to listen on"); + snprintf(dynamic_display, sizeof(dynamic_display), "%d", i); + display = dynamic_display; + } + + ListenTransFds = malloc(ListenTransCount * sizeof (int)); + + for (i = 0; i < ListenTransCount; i++) { + int fd = _XSERVTransGetConnectionNumber(ListenTransConns[i]); + + ListenTransFds[i] = fd; + FD_SET(fd, &WellKnownConnections); + + if (!_XSERVTransIsLocal(ListenTransConns[i])) + DefineSelf (fd); } if (!XFD_ANYSET (&WellKnownConnections)) diff --git a/nx-X11/programs/Xserver/os/utils.c b/nx-X11/programs/Xserver/os/utils.c index 25cbb1e87..929549168 100644 --- a/nx-X11/programs/Xserver/os/utils.c +++ b/nx-X11/programs/Xserver/os/utils.c @@ -780,6 +780,16 @@ ProcessCommandLine(int argc, char *argv[]) else UseMsg(); } + else if (strcmp(argv[i], "-displayfd") == 0) { + if (++i < argc) { + displayfd = atoi(argv[i]); + display = NULL; + nolock = TRUE; + } + else + UseMsg(); + } + #ifdef DPMSExtension else if ( strcmp( argv[i], "dpms") == 0) DPMSEnabledSwitch = TRUE; -- cgit v1.2.3 From e8bc4c7e2f42d21e41328b68d5dc2a15db73d47a Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Wed, 15 Mar 2017 14:56:17 +0000 Subject: os: Add a mechanism to prevent creating any listen sockets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 44fe1b8ea284df6bbaef67e246016d104665b2fe Author: Kristian Høgsberg Date: Wed Mar 19 14:03:13 2014 -0700 os: Add a mechanism to prevent creating any listen sockets A socket-activated server will receive its listening sockets from the parent process and should not create its own sockets. This patch introduces a NoListen flag that can be set by a DDX to prevent the server from creating the sockets. When NoListen is enabled, we also disable the server lock checking, since the parent process is responsible for checking the lock before picking the display name and creating the sockets. Signed-off-by: Kristian Høgsberg Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/include/opaque.h | 2 +- nx-X11/programs/Xserver/os/connection.c | 8 ++++++-- nx-X11/programs/Xserver/os/utils.c | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'nx-X11/programs/Xserver/include') diff --git a/nx-X11/programs/Xserver/include/opaque.h b/nx-X11/programs/Xserver/include/opaque.h index 8f98bf1be..1b84b9f5b 100644 --- a/nx-X11/programs/Xserver/include/opaque.h +++ b/nx-X11/programs/Xserver/include/opaque.h @@ -77,6 +77,6 @@ extern long maxBigRequestSize; extern Bool blackRoot; extern Bool CoreDump; - +extern Bool NoListenAll; #endif /* OPAQUE_H */ diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c index 6dc0ff64d..8958c47b5 100644 --- a/nx-X11/programs/Xserver/os/connection.c +++ b/nx-X11/programs/Xserver/os/connection.c @@ -137,6 +137,7 @@ int MaxClients = 0; int NumNotifyWriteFd; /* Number of NotifyFd members with write set */ Bool NewOutputPending; /* not yet attempted to write some new output */ Bool AnyWritesPending; /* true if some client blocked on write or NotifyFd with write */ +Bool NoListenAll; /* Don't establish any listening sockets */ Bool RunFromSmartParent; /* send SIGUSR1 to parent process */ static char dynamic_display[7]; /* display name */ Bool PartialNetwork; /* continue even if unable to bind all addrs */ @@ -411,7 +412,10 @@ CreateWellKnownSockets(void) /* display is initialized to "0" by main(). It is then set to the display * number if specified on the command line, or to NULL when the -displayfd * option is used. */ - if (display) { + if (NoListenAll) { + ListenTransCount = 0; + } + else if (display) { if (TryCreateSocket(atoi(display), &partial) && ListenTransCount >= 1) if (!PartialNetwork && partial) @@ -445,7 +449,7 @@ CreateWellKnownSockets(void) DefineSelf (fd); } - if (!XFD_ANYSET (&WellKnownConnections)) + if (!XFD_ANYSET (&WellKnownConnections) && !NoListenAll) FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running"); #if !defined(WIN32) OsSignal (SIGPIPE, SIG_IGN); diff --git a/nx-X11/programs/Xserver/os/utils.c b/nx-X11/programs/Xserver/os/utils.c index 929549168..74acb53ef 100644 --- a/nx-X11/programs/Xserver/os/utils.c +++ b/nx-X11/programs/Xserver/os/utils.c @@ -338,7 +338,7 @@ LockServer(void) int len; char port[20]; - if (nolock) return; + if (nolock || NoListenAll) return; /* * Path names */ @@ -464,7 +464,7 @@ LockServer(void) void UnlockServer(void) { - if (nolock) return; + if (nolock || NoListenAll) return; if (!StillLocking){ -- cgit v1.2.3 From 3be144ffde5f35df21ad115cbdedb8a072420edb Mon Sep 17 00:00:00 2001 From: Jon TURNEY Date: Wed, 15 Mar 2017 15:05:18 +0000 Subject: Handle -displayfd and an explicit display number sensibly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit bc348bd2c42f3f18786085ccef2f010eff5bf3d2 Author: Jon TURNEY Date: Mon Mar 11 14:34:32 2013 +0000 Handle -displayfd and an explicit display number sensibly Handle -displayfd and an explicit display number sensibly, e.g. use the explicitly specified display number, and write it to the displayfd v2: displayfd might be 0, so use -1 as invalid value v3: Rebase for addition of NoListenAll flag Signed-off-by: Jon TURNEY Reviewed-by: Kristian Høgsberg Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/dix/globals.c | 3 ++- nx-X11/programs/Xserver/include/opaque.h | 1 + nx-X11/programs/Xserver/os/connection.c | 11 +++++------ nx-X11/programs/Xserver/os/utils.c | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'nx-X11/programs/Xserver/include') diff --git a/nx-X11/programs/Xserver/dix/globals.c b/nx-X11/programs/Xserver/dix/globals.c index 5a3e22c26..f9fa544ed 100644 --- a/nx-X11/programs/Xserver/dix/globals.c +++ b/nx-X11/programs/Xserver/dix/globals.c @@ -149,7 +149,8 @@ int defaultColorVisualClass = -1; int monitorResolution = 0; char *display; -int displayfd; +int displayfd = -1; +Bool explicit_display = FALSE; CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND; int argcGlobal; diff --git a/nx-X11/programs/Xserver/include/opaque.h b/nx-X11/programs/Xserver/include/opaque.h index 1b84b9f5b..8312b4a21 100644 --- a/nx-X11/programs/Xserver/include/opaque.h +++ b/nx-X11/programs/Xserver/include/opaque.h @@ -53,6 +53,7 @@ extern int argcGlobal; extern char **argvGlobal; extern char *display; extern int displayfd; +extern Bool explicit_display; extern int defaultBackingStore; extern Bool disableBackingStore; diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c index 8958c47b5..7638cdfdd 100644 --- a/nx-X11/programs/Xserver/os/connection.c +++ b/nx-X11/programs/Xserver/os/connection.c @@ -361,8 +361,8 @@ void NotifyParentProcess(void) { #if !defined(WIN32) - if (dynamic_display[0]) { - write(displayfd, dynamic_display, strlen(dynamic_display)); + if (displayfd >= 0) { + write(displayfd, display, strlen(display)); close(displayfd); } if (RunFromSmartParent) { @@ -410,18 +410,17 @@ CreateWellKnownSockets(void) FD_ZERO (&WellKnownConnections); /* display is initialized to "0" by main(). It is then set to the display - * number if specified on the command line, or to NULL when the -displayfd - * option is used. */ + * number if specified on the command line. */ if (NoListenAll) { ListenTransCount = 0; } - else if (display) { + else if ((displayfd < 0) || explicit_display) { if (TryCreateSocket(atoi(display), &partial) && ListenTransCount >= 1) if (!PartialNetwork && partial) FatalError ("Failed to establish all listening sockets"); } - else { /* -displayfd */ + else { /* -displayfd and no explicit display number */ Bool found = 0; for (i = 0; i < 65535 - X_TCP_PORT; i++) { if (TryCreateSocket(i, &partial) && !partial) { diff --git a/nx-X11/programs/Xserver/os/utils.c b/nx-X11/programs/Xserver/os/utils.c index dce04e942..6995d05d5 100644 --- a/nx-X11/programs/Xserver/os/utils.c +++ b/nx-X11/programs/Xserver/os/utils.c @@ -704,6 +704,7 @@ ProcessCommandLine(int argc, char *argv[]) { /* initialize display */ display = argv[i]; + explicit_display = TRUE; display++; if( ! VerifyDisplayName( display ) ) { ErrorF("Bad display name: %s\n", display); @@ -783,7 +784,6 @@ ProcessCommandLine(int argc, char *argv[]) else if (strcmp(argv[i], "-displayfd") == 0) { if (++i < argc) { displayfd = atoi(argv[i]); - display = NULL; nolock = TRUE; } else -- cgit v1.2.3 From c468be804ec48231db12f504c2d877ef7a11adc1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 15 Mar 2017 15:16:37 +0000 Subject: os: Use NotifyFd interface for listen descriptors Bundle X.org backport of these commits: commit 7ea64fb4374504bd3d524fc08c90efdab9f253ea Author: Alan Coopersmith Date: Mon Mar 9 09:55:57 2015 -0700 Clear ListenTransConns entries in CloseWellKnownConnections Since _XSERVTransClose frees the connection pointer passed to it, remove that pointer from the array, so we don't try to double free it if we come back into CloseWellKnownConnections again. Should fix https://bugzilla.yoctoproject.org/show_bug.cgi?id=6665 in which the shutdown section of the main() loop called CloseWellKnownConnections() and then moved on to ddxGiveUp(), which failed to release the VT and thus called AbortServer(), which called CloseWellKnownConnections() again. Signed-off-by: Alan Coopersmith Reviewed-by: Adam Jackson Signed-off-by: Peter Hutterer commit 7b02f0b87ec2fa0cc5a65307a1fd55c671cec884 Author: Keith Packard Date: Wed Nov 11 22:02:17 2015 -0800 os: Use NotifyFd interface for listen descriptors Replace the custom path for dealing with new incoming connections with the general-purpose NotifyFd API. Reviewed-by: Adam Jackson Signed-off-by: Keith Packard commit ba71b69f94f00a6f6910597185610668e79c10be Author: Alan Coopersmith Date: Fri Jan 1 17:34:41 2016 -0800 Avoid segfault in CloseWellKnownConnections when using -displayfd When -displayfd is looping through the possible display ids to use, if it can't open all the listening sockets for one (say when :0 is already in use), it calls CloseWellKnownConnections to close all the ListenTransConns entries before the point that ListenTransFds was allocated & initialized, so CloseWellKnownConnections would segfault trying to read entries from a NULL ListenTransFds pointer. Introduced by commit 7b02f0b8 Signed-off-by: Alan Coopersmith Reviewed-by: Keith Packard Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/include/os.h | 4 -- nx-X11/programs/Xserver/os/WaitFor.c | 4 -- nx-X11/programs/Xserver/os/connection.c | 119 ++++++++++++++------------------ 3 files changed, 53 insertions(+), 74 deletions(-) (limited to 'nx-X11/programs/Xserver/include') diff --git a/nx-X11/programs/Xserver/include/os.h b/nx-X11/programs/Xserver/include/os.h index 5dd5e2012..1af34a04c 100644 --- a/nx-X11/programs/Xserver/include/os.h +++ b/nx-X11/programs/Xserver/include/os.h @@ -137,10 +137,6 @@ extern char *ClientAuthorized( unsigned int /*string_n*/, char* /*auth_string*/); -extern Bool EstablishNewConnections( - ClientPtr /*clientUnused*/, - void * /*closure*/); - extern void CheckConnections(void); extern void CloseDownConnection(ClientPtr /*client*/); diff --git a/nx-X11/programs/Xserver/os/WaitFor.c b/nx-X11/programs/Xserver/os/WaitFor.c index 4d7fe3f84..76e5da5f2 100644 --- a/nx-X11/programs/Xserver/os/WaitFor.c +++ b/nx-X11/programs/Xserver/os/WaitFor.c @@ -495,10 +495,6 @@ WaitForSomething(int *pClientsReady) } XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients); - XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections); - if (XFD_ANYSET(&tmp_set)) - QueueWorkProc(EstablishNewConnections, NULL, - (void *)&LastSelectMask); XFD_ANDSET(&tmp_set, &LastSelectMask, &NotifyReadFds); if (XFD_ANYSET(&tmp_set) || someNotifyWriteReady) diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c index 7638cdfdd..b251c2f5c 100644 --- a/nx-X11/programs/Xserver/os/connection.c +++ b/nx-X11/programs/Xserver/os/connection.c @@ -123,7 +123,6 @@ SOFTWARE. int lastfdesc; /* maximum file descriptor */ -fd_set WellKnownConnections; /* Listener mask */ fd_set NotifyReadFds; /* mask for other file descriptors */ fd_set NotifyWriteFds; /* mask for other write file descriptors */ fd_set AllSockets; /* select on this */ @@ -152,6 +151,9 @@ static fd_set SavedAllSockets; static fd_set SavedClientsWithInput; int GrabInProgress = 0; +static void +QueueNewConnections(int curconn, int ready, void *data); + #if !defined(WIN32) int *ConnectionTranslation = NULL; #else @@ -407,8 +409,6 @@ CreateWellKnownSockets(void) ClearConnectionTranslation(); #endif - FD_ZERO (&WellKnownConnections); - /* display is initialized to "0" by main(). It is then set to the display * number if specified on the command line. */ if (NoListenAll) { @@ -442,13 +442,13 @@ CreateWellKnownSockets(void) int fd = _XSERVTransGetConnectionNumber(ListenTransConns[i]); ListenTransFds[i] = fd; - FD_SET(fd, &WellKnownConnections); + SetNotifyFd(fd, QueueNewConnections, X_NOTIFY_READ, NULL); if (!_XSERVTransIsLocal(ListenTransConns[i])) DefineSelf (fd); } - if (!XFD_ANYSET (&WellKnownConnections) && !NoListenAll) + if (ListenTransCount == 0 && !NoListenAll) FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running"); #if !defined(WIN32) OsSignal (SIGPIPE, SIG_IGN); @@ -456,7 +456,6 @@ CreateWellKnownSockets(void) #endif OsSignal (SIGINT, GiveUp); OsSignal (SIGTERM, GiveUp); - XFD_COPYSET (&WellKnownConnections, &AllSockets); ResetHosts(display); InitParentProcess(); @@ -525,7 +524,7 @@ ResetWellKnownSockets (void) * Remove it from out list. */ - FD_CLR (ListenTransFds[i], &WellKnownConnections); + RemoveNotifyFd(ListenTransFds[i]); ListenTransFds[i] = ListenTransFds[ListenTransCount - 1]; ListenTransConns[i] = ListenTransConns[ListenTransCount - 1]; ListenTransCount -= 1; @@ -539,13 +538,14 @@ ResetWellKnownSockets (void) int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); - FD_CLR (ListenTransFds[i], &WellKnownConnections); ListenTransFds[i] = newfd; - FD_SET(newfd, &WellKnownConnections); } } } + for (i = 0; i < ListenTransCount; i++) + SetNotifyFd(ListenTransFds[i], QueueNewConnections, X_NOTIFY_READ, NULL); + ResetAuthorization (); ResetHosts(display); /* @@ -561,8 +561,15 @@ CloseWellKnownConnections(void) { int i; - for (i = 0; i < ListenTransCount; i++) - _XSERVTransClose (ListenTransConns[i]); + for (i = 0; i < ListenTransCount; i++) { + if (ListenTransConns[i] != NULL) { + _XSERVTransClose(ListenTransConns[i]); + ListenTransConns[i] = NULL; + if (ListenTransFds != NULL) + RemoveNotifyFd(ListenTransFds[i]); + } + } + ListenTransCount = 0; } static void @@ -827,23 +834,18 @@ AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time) * and AllSockets. *****************/ -/*ARGSUSED*/ -Bool +static Bool EstablishNewConnections(ClientPtr clientUnused, void * closure) { - fd_set readyconnections; /* set of listeners that are ready */ - int curconn; /* fd of listener that's ready */ - register int newconn; /* fd of new client */ + int curconn = (int) (intptr_t) closure; + int newconn; /* fd of new client */ CARD32 connect_time; - register int i; - register ClientPtr client; - register OsCommPtr oc; - fd_set tmask; - - XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections); - XFD_COPYSET(&tmask, &readyconnections); - if (!XFD_ANYSET(&readyconnections)) - return TRUE; + int i; + ClientPtr client; + OsCommPtr oc; + XtransConnInfo trans_conn, new_trans_conn; + int status; + connect_time = GetTimeInMillis(); /* kill off stragglers */ for (i=1; iflags & TRANS_NOXAUTH) + new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH; + + if (!AllocNewConnection(new_trans_conn, newconn, connect_time)) { + ErrorConnMax(new_trans_conn); + } - if (!AllocNewConnection (new_trans_conn, newconn, connect_time - )) - { - ErrorConnMax(new_trans_conn); - } - } -#ifndef WIN32 - } -#endif return TRUE; } +static void +QueueNewConnections(int fd, int ready, void *data) +{ + QueueWorkProc(EstablishNewConnections, NULL, (void *) (intptr_t) fd); +} + #define NOROOM "Maximum number of clients reached" /************ -- cgit v1.2.3 From e96e810c2287232000767ee55f2d1b84b31e6291 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Wed, 15 Mar 2017 15:42:10 +0000 Subject: Use unique logfile names when starting server with -displayfd commit edcb6426f20c3be5dd5f50b76a686754aef2f64e Author: Alan Coopersmith Date: Fri Jan 1 18:11:14 2016 -0800 Use unique logfile names when starting server with -displayfd Fixes https://bugs.freedesktop.org/show_bug.cgi?id=93212 Previously all X servers started with -displayfd would overwrite Xorg.0.log - now a temporary name of Xorg.pid-.log is used until after -displayfd finds an open display - then it is renamed to the traditional Xorg..log name. Reviewed-by: Adam Jackson Signed-off-by: Alan Coopersmith Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/include/os.h | 1 + nx-X11/programs/Xserver/os/connection.c | 1 + nx-X11/programs/Xserver/os/log.c | 127 ++++++++++++++++++++++++-------- 3 files changed, 100 insertions(+), 29 deletions(-) (limited to 'nx-X11/programs/Xserver/include') diff --git a/nx-X11/programs/Xserver/include/os.h b/nx-X11/programs/Xserver/include/os.h index 1af34a04c..0c7ce6a6f 100644 --- a/nx-X11/programs/Xserver/include/os.h +++ b/nx-X11/programs/Xserver/include/os.h @@ -520,6 +520,7 @@ typedef enum { #endif extern const char *LogInit(const char *fname, const char *backup); +extern void LogSetDisplay(void); extern void LogClose(void); extern Bool LogSetParameter(LogParameter param, int value); extern void LogVWrite(int verb, const char *f, va_list args); diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c index 0d48fda5b..940b0bd75 100644 --- a/nx-X11/programs/Xserver/os/connection.c +++ b/nx-X11/programs/Xserver/os/connection.c @@ -434,6 +434,7 @@ CreateWellKnownSockets(void) FatalError("Failed to find a socket to listen on"); snprintf(dynamic_display, sizeof(dynamic_display), "%d", i); display = dynamic_display; + LogSetDisplay(); } ListenTransFds = malloc(ListenTransCount * sizeof (int)); diff --git a/nx-X11/programs/Xserver/os/log.c b/nx-X11/programs/Xserver/os/log.c index d82f545a0..0ead6e9f0 100644 --- a/nx-X11/programs/Xserver/os/log.c +++ b/nx-X11/programs/Xserver/os/log.c @@ -178,49 +178,88 @@ static Bool needBuffer = TRUE; #define X_NOT_IMPLEMENTED_STRING "(NI)" #endif +/* + * LogFilePrep is called to setup files for logging, including getting + * an old file out of the way, but it doesn't actually open the file, + * since it may be used for renaming a file we're already logging to. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + +static char * +LogFilePrep(const char *fname, const char *backup, const char *idstring) +{ + char *logFileName = NULL; + + if (asprintf(&logFileName, fname, idstring) == -1) + FatalError("Cannot allocate space for the log file name\n"); + + if (backup && *backup) { + struct stat buf; + + if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { + char *suffix; + char *oldLog; + + if ((asprintf(&suffix, backup, idstring) == -1) || + (asprintf(&oldLog, "%s%s", logFileName, suffix) == -1)) { + FatalError("Cannot allocate space for the log file name\n"); + } + free(suffix); + + if (rename(logFileName, oldLog) == -1) { + FatalError("Cannot move old log file \"%s\" to \"%s\"\n", + logFileName, oldLog); + } + free(oldLog); + } + } + else { + if (remove(logFileName) != 0) { + FatalError("Cannot remove old log file \"%s\": %s\n", + logFileName, strerror(errno)); + } + } + + return logFileName; +} +#pragma GCC diagnostic pop + /* * LogInit is called to start logging to a file. It is also called (with * NULL arguments) when logging to a file is not wanted. It must always be * called, otherwise log messages will continue to accumulate in a buffer. * * %s, if present in the fname or backup strings, is expanded to the display - * string. + * string (or to a string containing the pid if the display is not yet set). */ +static char *saved_log_fname; +static char *saved_log_backup; +static char *saved_log_tempname; + const char * LogInit(const char *fname, const char *backup) { char *logFileName = NULL; if (fname && *fname) { - /* malloc() can't be used yet. */ - logFileName = malloc(strlen(fname) + strlen(display) + 1); - if (!logFileName) - FatalError("Cannot allocate space for the log file name\n"); - sprintf(logFileName, fname, display); - - if (backup && *backup) { - struct stat buf; - - if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { - char *suffix; - char *oldLog; - - oldLog = malloc(strlen(logFileName) + strlen(backup) + - strlen(display) + 1); - suffix = malloc(strlen(backup) + strlen(display) + 1); - if (!oldLog || !suffix) - FatalError("Cannot allocate space for the log file name\n"); - sprintf(suffix, backup, display); - sprintf(oldLog, "%s%s", logFileName, suffix); - free(suffix); - if (rename(logFileName, oldLog) == -1) { - FatalError("Cannot move old log file (\"%s\" to \"%s\"\n", - logFileName, oldLog); - } - free(oldLog); - } - } + if (displayfd != -1) { + /* Display isn't set yet, so we can't use it in filenames yet. */ + char pidstring[32]; + snprintf(pidstring, sizeof(pidstring), "pid-%ld", + (unsigned long) getpid()); + logFileName = LogFilePrep(fname, backup, pidstring); + saved_log_tempname = logFileName; + + /* Save the patterns for use when the display is named. */ + saved_log_fname = strdup(fname); + if (backup == NULL) + saved_log_backup = NULL; + else + saved_log_backup = strdup(backup); + } else + logFileName = LogFilePrep(fname, backup, display); if ((logFile = fopen(logFileName, "w")) == NULL) FatalError("Cannot open log file \"%s\"\n", logFileName); setvbuf(logFile, NULL, _IONBF, 0); @@ -249,6 +288,36 @@ LogInit(const char *fname, const char *backup) return logFileName; } +void +LogSetDisplay(void) +{ + if (saved_log_fname) { + char *logFileName; + + logFileName = LogFilePrep(saved_log_fname, saved_log_backup, display); + + if (rename(saved_log_tempname, logFileName) == 0) { + LogMessageVerb(X_PROBED, 0, + "Log file renamed from \"%s\" to \"%s\"\n", + saved_log_tempname, logFileName); + + if (strlen(saved_log_tempname) >= strlen(logFileName)) + strncpy(saved_log_tempname, logFileName, + strlen(saved_log_tempname)); + } + else { + ErrorF("Failed to rename log file \"%s\" to \"%s\": %s\n", + saved_log_tempname, logFileName, strerror(errno)); + } + + /* free newly allocated string - can't free old one since existing + pointers to it may exist in DDX callers. */ + free(logFileName); + free(saved_log_fname); + free(saved_log_backup); + } +} + void LogClose() { -- cgit v1.2.3