From f14f738a627b5a6f6c1242f4fe123e4cc9e9c811 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 16 Feb 2017 15:04:43 +0000 Subject: dix/os: Merge priority computation into SmartScheduleClient Backported from X.org: commit 7762a602c1dfdd8cfcf2b8c2281cf4d683d05216 Author: Keith Packard Date: Thu May 19 15:05:55 2016 -0700 dix/os: Merge priority computation into SmartScheduleClient Instead of having scheduling done in two places (one in WaitForSomething, and the other in SmartScheduleClient), just stick all of the scheduling in SmartScheduleClient. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/dix/dispatch.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'nx-X11/programs/Xserver/dix') diff --git a/nx-X11/programs/Xserver/dix/dispatch.c b/nx-X11/programs/Xserver/dix/dispatch.c index 7b2aa7b3d..68c207e33 100644 --- a/nx-X11/programs/Xserver/dix/dispatch.c +++ b/nx-X11/programs/Xserver/dix/dispatch.c @@ -240,15 +240,13 @@ void InitProcVectors(void); int SmartScheduleClient (int *clientReady, int nready) { - ClientPtr pClient; int i; int client; - int bestPrio, best = 0; + ClientPtr pClient, best = NULL; int bestRobin, robin; long now = SmartScheduleTime; long idle; - bestPrio = -0x7fffffff; bestRobin = 0; idle = 2 * SmartScheduleSlice; for (i = 0; i < nready; i++) @@ -264,13 +262,19 @@ SmartScheduleClient (int *clientReady, int nready) pClient->smart_check_tick = now; /* check priority to select best client */ - robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff; - if (pClient->smart_priority > bestPrio || - (pClient->smart_priority == bestPrio && robin > bestRobin)) + robin = (pClient->index - + SmartLastIndex[pClient->smart_priority - + SMART_MIN_PRIORITY]) & 0xff; + + /* pick the best client */ + if (!best || + pClient->priority > best->priority || + (pClient->priority == best->priority && + (pClient->smart_priority > best->smart_priority || + (pClient->smart_priority == best->smart_priority && robin > bestRobin)))) { - bestPrio = pClient->smart_priority; + best = pClient; bestRobin = robin; - best = client; } #ifdef SMART_DEBUG if ((now - SmartLastPrint) >= 5000) @@ -284,8 +288,7 @@ SmartScheduleClient (int *clientReady, int nready) SmartLastPrint = now; } #endif - pClient = clients[best]; - SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index; + SmartLastIndex[best->smart_priority - SMART_MIN_PRIORITY] = best->index; /* * Set current client pointer */ @@ -314,7 +317,7 @@ SmartScheduleClient (int *clientReady, int nready) { SmartScheduleSlice = SmartScheduleInterval; } - return best; + return best->index; } #ifndef NXAGENT_SERVER -- 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/dix') 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/dix') 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 4f76ed19b8a7b9448e29ac152f7f5ec1e611950e Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 16 Feb 2017 10:54:19 +0000 Subject: dix: Extend initial connection handshake for forwarding proxies commit 78fa121f4097d29458e5453c13473595df06e26e Author: Adam Jackson Date: Fri Jun 17 13:43:38 2011 -0400 dix: Extend initial connection handshake for forwarding proxies Forwarding proxies like sshd will appear to be local, even though they aren't really. This leads to weird behaviour for extensions that truly require running under the same OS services as the client, like MIT-SHM and DRI2. Add two new legal values for the initial connection's byteOrder field, 'r' and 'R'. These act like 'l' and 'B' respectively, but have the side effect of forcing the client to be treated as non-local. Forwarding proxies should attempt to munge the first packet of the connection accordingly; older servers will reject connections thusly munged, so the proxy should fall back to passthrough if the munged connection attempt fails. Reviewed-by: Daniel Stone Signed-off-by: Adam Jackson Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/dix/dispatch.c | 12 +++++++++--- nx-X11/programs/Xserver/os/connection.c | 10 +++++----- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'nx-X11/programs/Xserver/dix') diff --git a/nx-X11/programs/Xserver/dix/dispatch.c b/nx-X11/programs/Xserver/dix/dispatch.c index 16b94301f..438436526 100644 --- a/nx-X11/programs/Xserver/dix/dispatch.c +++ b/nx-X11/programs/Xserver/dix/dispatch.c @@ -3752,12 +3752,14 @@ ProcInitialConnection(register ClientPtr client) REQUEST(xReq); register xConnClientPrefix *prefix; int whichbyte = 1; + char order; prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); - if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) + order = prefix->byteOrder; + if (order != 'l' && order != 'B' && order != 'r' && order != 'R') return (client->noClientException = -1); - if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || - (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) + if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || + (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { client->swapped = TRUE; SwapConnClientPrefix(prefix); @@ -3769,6 +3771,10 @@ ProcInitialConnection(register ClientPtr client) { swaps(&stuff->length); } + if (order == 'r' || order == 'R') + { + client->local = FALSE; + } ResetCurrentRequest(client); return (client->noClientException); } diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c index 917f79fa6..d4627e97c 100644 --- a/nx-X11/programs/Xserver/os/connection.c +++ b/nx-X11/programs/Xserver/os/connection.c @@ -886,7 +886,7 @@ ErrorConnMax(XtransConnInfo trans_conn) xConnSetupPrefix csp; char pad[3]; struct iovec iov[3]; - char byteOrder = 0; + char order = 0; int whichbyte = 1; struct timeval waittime; fd_set mask; @@ -899,16 +899,16 @@ ErrorConnMax(XtransConnInfo trans_conn) FD_SET(fd, &mask); (void)Select(fd + 1, &mask, NULL, NULL, &waittime); /* try to read the byte-order of the connection */ - (void)_XSERVTransRead(trans_conn, &byteOrder, 1); - if ((byteOrder == 'l') || (byteOrder == 'B')) + (void)_XSERVTransRead(trans_conn, &order, 1); + if (order == 'l' || order == 'B' || order == 'r' || order == 'R') { csp.success = xFalse; csp.lengthReason = sizeof(NOROOM) - 1; csp.length = (sizeof(NOROOM) + 2) >> 2; csp.majorVersion = X_PROTOCOL; csp.minorVersion = X_PROTOCOL_REVISION; - if (((*(char *) &whichbyte) && (byteOrder == 'B')) || - (!(*(char *) &whichbyte) && (byteOrder == 'l'))) + if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || + (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { swaps(&csp.majorVersion); swaps(&csp.minorVersion); -- 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/dix') 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/dix') 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 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/dix') 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