@@ -371,6 +371,9 @@ struct ipc_server_data {
371
371
HANDLE hEventStopRequested ;
372
372
struct ipc_server_thread_data * thread_list ;
373
373
int is_stopped ;
374
+
375
+ pthread_mutex_t startup_barrier ;
376
+ int started ;
374
377
};
375
378
376
379
enum connect_result {
@@ -526,6 +529,16 @@ static int use_connection(struct ipc_server_thread_data *server_thread_data)
526
529
return ret ;
527
530
}
528
531
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
+
529
542
/*
530
543
* Thread proc for an IPC server worker thread. It handles a series of
531
544
* connections from clients. It cleans and reuses the hPipe between each
@@ -550,6 +563,8 @@ static void *server_thread_proc(void *_server_thread_data)
550
563
memset (& oConnect , 0 , sizeof (oConnect ));
551
564
oConnect .hEvent = hEventConnected ;
552
565
566
+ wait_for_startup_barrier (server_thread_data -> server_data );
567
+
553
568
for (;;) {
554
569
cr = wait_for_connection (server_thread_data , & oConnect );
555
570
@@ -752,10 +767,10 @@ static HANDLE create_new_pipe(wchar_t *wpath, int is_first)
752
767
return hPipe ;
753
768
}
754
769
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 )
759
774
{
760
775
struct ipc_server_data * server_data ;
761
776
wchar_t wpath [MAX_PATH ];
@@ -787,6 +802,13 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data,
787
802
strbuf_addstr (& server_data -> buf_path , path );
788
803
wcscpy (server_data -> wpath , wpath );
789
804
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
+
790
812
if (nr_threads < 1 )
791
813
nr_threads = 1 ;
792
814
@@ -837,6 +859,15 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data,
837
859
return 0 ;
838
860
}
839
861
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
+
840
871
int ipc_server_stop_async (struct ipc_server_data * server_data )
841
872
{
842
873
if (!server_data )
@@ -850,6 +881,13 @@ int ipc_server_stop_async(struct ipc_server_data *server_data)
850
881
* We DO NOT attempt to force them to drop an active connection.
851
882
*/
852
883
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
+
853
891
return 0 ;
854
892
}
855
893
@@ -900,5 +938,7 @@ void ipc_server_free(struct ipc_server_data *server_data)
900
938
free (std );
901
939
}
902
940
941
+ pthread_mutex_destroy (& server_data -> startup_barrier );
942
+
903
943
free (server_data );
904
944
}
0 commit comments