diff --git a/dix/dispatch.c b/dix/dispatch.c index cc7eea874..460296197 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -165,6 +165,7 @@ static int nextFreeClientID; /* always MIN free client ID */ static int nClients; /* number of authorized clients */ CallbackListPtr ClientStateCallback; +OsTimerPtr dispatchExceptionTimer; /* dispatchException & isItTimeToYield must be declared volatile since they * are modified by signal handlers - otherwise optimizer may assume it doesn't @@ -400,6 +401,42 @@ SmartScheduleClient(void) return best; } +static CARD32 +DispatchExceptionCallback(OsTimerPtr timer, CARD32 time, void *arg) +{ + dispatchException |= dispatchExceptionAtReset; + + /* Don't re-arm the timer */ + return 0; +} + +static void +CancelDispatchExceptionTimer(void) +{ + TimerFree(dispatchExceptionTimer); + dispatchExceptionTimer = NULL; +} + +static void +SetDispatchExceptionTimer(void) +{ + /* The timer delay is only for terminate, not reset */ + if (!(dispatchExceptionAtReset & DE_TERMINATE)) { + dispatchException |= dispatchExceptionAtReset; + return; + } + + CancelDispatchExceptionTimer(); + + if (terminateDelay == 0) + dispatchException |= dispatchExceptionAtReset; + else + dispatchExceptionTimer = TimerSet(dispatchExceptionTimer, + 0, terminateDelay * 1000 /* msec */, + &DispatchExceptionCallback, + NULL); +} + static Bool ShouldDisconnectRemainingClients(void) { @@ -3436,6 +3473,7 @@ ProcNoOperation(ClientPtr client) *********************/ char dispatchExceptionAtReset = DE_RESET; +int terminateDelay = 0; void CloseDownClient(ClientPtr client) @@ -3492,7 +3530,7 @@ CloseDownClient(ClientPtr client) if (really_close_down) { if (client->clientState == ClientStateRunning && nClients == 0) - dispatchException |= dispatchExceptionAtReset; + SetDispatchExceptionTimer(); client->clientState = ClientStateGone; if (ClientStateCallback) { @@ -3523,7 +3561,7 @@ CloseDownClient(ClientPtr client) } if (ShouldDisconnectRemainingClients()) - dispatchException |= dispatchExceptionAtReset; + SetDispatchExceptionTimer(); } static void @@ -3725,6 +3763,7 @@ SendConnSetup(ClientPtr client, const char *reason) clientinfo.setup = (xConnSetup *) lConnectionInfo; CallCallbacks((&ClientStateCallback), (void *) &clientinfo); } + CancelDispatchExceptionTimer(); return Success; } diff --git a/hw/xwayland/xwayland.pc.in b/hw/xwayland/xwayland.pc.in index f6165a65b..8816bb6e9 100644 --- a/hw/xwayland/xwayland.pc.in +++ b/hw/xwayland/xwayland.pc.in @@ -10,3 +10,4 @@ have_eglstream=@have_eglstream@ have_initfd=true have_listenfd=true have_verbose=true +have_terminate_delay=true diff --git a/include/dix.h b/include/dix.h index 432bdcc35..ff3a18ccf 100644 --- a/include/dix.h +++ b/include/dix.h @@ -130,6 +130,7 @@ extern _X_EXPORT ClientPtr clients[MAXCLIENTS]; extern _X_EXPORT ClientPtr serverClient; extern _X_EXPORT int currentMaxClients; extern _X_EXPORT char dispatchExceptionAtReset; +extern _X_EXPORT int terminateDelay; typedef int HWEventQueueType; typedef HWEventQueueType *HWEventQueuePtr; diff --git a/man/Xserver.man b/man/Xserver.man index 27ce83279..2b7442d7e 100644 --- a/man/Xserver.man +++ b/man/Xserver.man @@ -263,11 +263,14 @@ connected to the system. sets pointer acceleration threshold in pixels (i.e. after how many pixels pointer acceleration should take effect). .TP 8 -.B \-terminate +.B \-terminate \fI[delay]\fP causes the server to terminate at server reset, instead of continuing to run. This overrides a previous .B \-noreset command line option. +If a delay in seconds is specified, the server waits for at least +the delay. At the end of this grace period if no client is +connected, the server terminates immediately. .TP 8 .B \-tst disables all testing extensions (e.g., XTEST, XTrap, XTestExtension1, RECORD). diff --git a/os/utils.c b/os/utils.c index 6cefc02ac..c3565f971 100644 --- a/os/utils.c +++ b/os/utils.c @@ -561,7 +561,7 @@ UseMsg(void) ErrorF("-s # screen-saver timeout (minutes)\n"); ErrorF("-seat string seat to run on\n"); ErrorF("-t # default pointer threshold (pixels/t)\n"); - ErrorF("-terminate terminate at server reset\n"); + ErrorF("-terminate [delay] terminate at server reset (optional delay in sec)\n"); ErrorF("-tst disable testing extensions\n"); ErrorF("ttyxx server started from init on /dev/ttyxx\n"); ErrorF("v video blanking for screen-saver\n"); @@ -917,6 +917,10 @@ ProcessCommandLine(int argc, char *argv[]) } else if (strcmp(argv[i], "-terminate") == 0) { dispatchExceptionAtReset = DE_TERMINATE; + terminateDelay = -1; + if ((i + 1 < argc) && (isdigit(*argv[i + 1]))) + terminateDelay = atoi(argv[++i]); + terminateDelay = max(0, terminateDelay); } else if (strcmp(argv[i], "-tst") == 0) { noTestExtensions = TRUE;