@ -11,6 +11,7 @@
# include "config.h"
# include "command.h"
# include "util/lock.h"
# include "util/log.h"
# include "util/net.h"
# include "util/str_util.h"
@ -361,6 +362,19 @@ server_init(struct server *server) {
atomic_flag_clear_explicit ( & server - > server_socket_closed ,
memory_order_relaxed ) ;
server - > mutex = SDL_CreateMutex ( ) ;
if ( ! server - > mutex ) {
return false ;
}
server - > process_terminated_cond = SDL_CreateCond ( ) ;
if ( ! server - > process_terminated_cond ) {
SDL_DestroyMutex ( server - > mutex ) ;
return false ;
}
server - > process_terminated = false ;
server - > server_socket = INVALID_SOCKET ;
server - > video_socket = INVALID_SOCKET ;
server - > control_socket = INVALID_SOCKET ;
@ -379,6 +393,12 @@ static int
run_wait_server ( void * data ) {
struct server * server = data ;
cmd_simple_wait ( server - > process , NULL ) ; // ignore exit code
mutex_lock ( server - > mutex ) ;
server - > process_terminated = true ;
cond_signal ( server - > process_terminated_cond ) ;
mutex_unlock ( server - > mutex ) ;
// no need for synchronization, server_socket is initialized before this
// thread was created
if ( server - > server_socket ! = INVALID_SOCKET
@ -510,17 +530,39 @@ server_stop(struct server *server) {
assert ( server - > process ! = PROCESS_NONE ) ;
cmd_terminate ( server - > process ) ;
if ( server - > tunnel_enabled ) {
// ignore failure
disable_tunnel ( server ) ;
}
// Give some delay for the server to terminate properly
mutex_lock ( server - > mutex ) ;
int r = 0 ;
if ( ! server - > process_terminated ) {
# define WATCHDOG_DELAY_MS 1000
r = cond_wait_timeout ( server - > process_terminated_cond ,
server - > mutex ,
WATCHDOG_DELAY_MS ) ;
}
mutex_unlock ( server - > mutex ) ;
// After this delay, kill the server if it's not dead already.
// On some devices, closing the sockets is not sufficient to wake up the
// blocking calls while the device is asleep.
if ( r = = SDL_MUTEX_TIMEDOUT ) {
// FIXME There is a race condition here: there is a small chance that
// the process is already terminated, and the PID assigned to a new
// process.
LOGW ( " Killing the server... " ) ;
cmd_terminate ( server - > process ) ;
}
SDL_WaitThread ( server - > wait_server_thread , NULL ) ;
}
void
server_destroy ( struct server * server ) {
SDL_free ( server - > serial ) ;
SDL_DestroyCond ( server - > process_terminated_cond ) ;
SDL_DestroyMutex ( server - > mutex ) ;
}