@@ -371,6 +371,9 @@ struct ipc_server_data {
371371 HANDLE hEventStopRequested ;
372372 struct ipc_server_thread_data * thread_list ;
373373 int is_stopped ;
374+
375+ pthread_mutex_t startup_barrier ;
376+ int started ;
374377};
375378
376379enum connect_result {
@@ -526,6 +529,16 @@ static int use_connection(struct ipc_server_thread_data *server_thread_data)
526529 return ret ;
527530}
528531
532+ static void wait_for_startup_barrier (struct ipc_server_data * server_data )
533+ {
534+ /*
535+ * Temporarily hold the startup_barrier mutex before starting,
536+ * which lets us know that it's OK to start serving requests.
537+ */
538+ pthread_mutex_lock (& server_data -> startup_barrier );
539+ pthread_mutex_unlock (& server_data -> startup_barrier );
540+ }
541+
529542/*
530543 * Thread proc for an IPC server worker thread. It handles a series of
531544 * connections from clients. It cleans and reuses the hPipe between each
@@ -550,6 +563,8 @@ static void *server_thread_proc(void *_server_thread_data)
550563 memset (& oConnect , 0 , sizeof (oConnect ));
551564 oConnect .hEvent = hEventConnected ;
552565
566+ wait_for_startup_barrier (server_thread_data -> server_data );
567+
553568 for (;;) {
554569 cr = wait_for_connection (server_thread_data , & oConnect );
555570
@@ -752,10 +767,10 @@ static HANDLE create_new_pipe(wchar_t *wpath, int is_first)
752767 return hPipe ;
753768}
754769
755- int ipc_server_run_async (struct ipc_server_data * * returned_server_data ,
756- const char * path , const struct ipc_server_opts * opts ,
757- ipc_server_application_cb * application_cb ,
758- void * application_data )
770+ int ipc_server_init_async (struct ipc_server_data * * returned_server_data ,
771+ const char * path , const struct ipc_server_opts * opts ,
772+ ipc_server_application_cb * application_cb ,
773+ void * application_data )
759774{
760775 struct ipc_server_data * server_data ;
761776 wchar_t wpath [MAX_PATH ];
@@ -787,6 +802,13 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data,
787802 strbuf_addstr (& server_data -> buf_path , path );
788803 wcscpy (server_data -> wpath , wpath );
789804
805+ /*
806+ * Hold the startup_barrier lock so that no threads will progress
807+ * until ipc_server_start_async() is called.
808+ */
809+ pthread_mutex_init (& server_data -> startup_barrier , NULL );
810+ pthread_mutex_lock (& server_data -> startup_barrier );
811+
790812 if (nr_threads < 1 )
791813 nr_threads = 1 ;
792814
@@ -837,6 +859,15 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data,
837859 return 0 ;
838860}
839861
862+ void ipc_server_start_async (struct ipc_server_data * server_data )
863+ {
864+ if (!server_data || server_data -> started )
865+ return ;
866+
867+ server_data -> started = 1 ;
868+ pthread_mutex_unlock (& server_data -> startup_barrier );
869+ }
870+
840871int ipc_server_stop_async (struct ipc_server_data * server_data )
841872{
842873 if (!server_data )
@@ -850,6 +881,13 @@ int ipc_server_stop_async(struct ipc_server_data *server_data)
850881 * We DO NOT attempt to force them to drop an active connection.
851882 */
852883 SetEvent (server_data -> hEventStopRequested );
884+
885+ /*
886+ * If we haven't yet told the threads they are allowed to run,
887+ * do so now, so they can receive the shutdown event.
888+ */
889+ ipc_server_start_async (server_data );
890+
853891 return 0 ;
854892}
855893
@@ -900,5 +938,7 @@ void ipc_server_free(struct ipc_server_data *server_data)
900938 free (std );
901939 }
902940
941+ pthread_mutex_destroy (& server_data -> startup_barrier );
942+
903943 free (server_data );
904944}
0 commit comments