@@ -86,6 +86,8 @@ static int do_as_client__send_stop(void)
8686{
8787 struct strbuf answer = STRBUF_INIT ;
8888 int ret ;
89+ int max_wait_ms = 30000 ;
90+ int elapsed_ms = 0 ;
8991
9092 ret = fsmonitor_ipc__send_command ("quit" , & answer );
9193
@@ -96,8 +98,16 @@ static int do_as_client__send_stop(void)
9698 return ret ;
9799
98100 trace2_region_enter ("fsm_client" , "polling-for-daemon-exit" , NULL );
99- while (fsmonitor_ipc__get_state () == IPC_STATE__LISTENING )
101+ while (fsmonitor_ipc__get_state () == IPC_STATE__LISTENING ) {
102+ if (elapsed_ms >= max_wait_ms ) {
103+ trace2_region_leave ("fsm_client" ,
104+ "polling-for-daemon-exit" , NULL );
105+ return error (_ ("daemon did not stop within %d seconds" ),
106+ max_wait_ms / 1000 );
107+ }
100108 sleep_millisec (50 );
109+ elapsed_ms += 50 ;
110+ }
101111 trace2_region_leave ("fsm_client" , "polling-for-daemon-exit" , NULL );
102112
103113 return 0 ;
@@ -197,20 +207,31 @@ static enum fsmonitor_cookie_item_result with_lock__wait_for_cookie(
197207 unlink (cookie_pathname .buf );
198208
199209 /*
200- * Technically, this is an infinite wait (well, unless another
201- * thread sends us an abort). I'd like to change this to
202- * use `pthread_cond_timedwait()` and return an error/timeout
203- * and let the caller do the trivial response thing, but we
204- * don't have that routine in our thread-utils.
205- *
206- * After extensive beta testing I'm not really worried about
207- * this. Also note that the above open() and unlink() calls
208- * will cause at least two FS events on that path, so the odds
209- * of getting stuck are pretty slim.
210+ * Wait for the listener thread to observe the cookie file.
211+ * Time out after a short interval so that the client
212+ * does not hang forever if the filesystem does not deliver
213+ * events (e.g., on certain container/overlay filesystems
214+ * where inotify watches succeed but events never arrive).
210215 */
211- while (cookie -> result == FCIR_INIT )
212- pthread_cond_wait (& state -> cookies_cond ,
213- & state -> main_lock );
216+ {
217+ struct timeval now ;
218+ struct timespec ts ;
219+ int err = 0 ;
220+
221+ gettimeofday (& now , NULL );
222+ ts .tv_sec = now .tv_sec + 1 ;
223+ ts .tv_nsec = now .tv_usec * 1000 ;
224+
225+ while (cookie -> result == FCIR_INIT && !err )
226+ err = pthread_cond_timedwait (& state -> cookies_cond ,
227+ & state -> main_lock ,
228+ & ts );
229+ if (err == ETIMEDOUT && cookie -> result == FCIR_INIT ) {
230+ trace_printf_key (& trace_fsmonitor ,
231+ "cookie_wait timed out" );
232+ cookie -> result = FCIR_ERROR ;
233+ }
234+ }
214235
215236done :
216237 hashmap_remove (& state -> cookies , & cookie -> entry , NULL );
@@ -671,7 +692,7 @@ static int do_handle_client(struct fsmonitor_daemon_state *state,
671692 const struct fsmonitor_batch * batch ;
672693 struct fsmonitor_batch * remainder = NULL ;
673694 intmax_t count = 0 , duplicates = 0 ;
674- kh_str_t * shown ;
695+ kh_str_t * shown = NULL ;
675696 int hash_ret ;
676697 int do_trivial = 0 ;
677698 int do_flush = 0 ;
@@ -909,8 +930,6 @@ static int do_handle_client(struct fsmonitor_daemon_state *state,
909930 total_response_len += payload .len ;
910931 }
911932
912- kh_release_str (shown );
913-
914933 pthread_mutex_lock (& state -> main_lock );
915934
916935 if (token_data -> client_ref_count > 0 )
@@ -954,6 +973,7 @@ static int do_handle_client(struct fsmonitor_daemon_state *state,
954973 trace2_data_intmax ("fsmonitor" , the_repository , "response/count/duplicates" , duplicates );
955974
956975cleanup :
976+ kh_destroy_str (shown );
957977 strbuf_release (& response_token );
958978 strbuf_release (& requested_token_id );
959979 strbuf_release (& payload );
@@ -1405,6 +1425,7 @@ static int fsmonitor_run_daemon(void)
14051425done :
14061426 pthread_cond_destroy (& state .cookies_cond );
14071427 pthread_mutex_destroy (& state .main_lock );
1428+ hashmap_clear (& state .cookies );
14081429 fsm_listen__dtor (& state );
14091430 fsm_health__dtor (& state );
14101431
@@ -1420,7 +1441,7 @@ static int fsmonitor_run_daemon(void)
14201441 return err ;
14211442}
14221443
1423- static int try_to_run_foreground_daemon (int detach_console MAYBE_UNUSED )
1444+ static int try_to_run_foreground_daemon (int detach_console )
14241445{
14251446 /*
14261447 * Technically, we don't need to probe for an existing daemon
@@ -1440,10 +1461,21 @@ static int try_to_run_foreground_daemon(int detach_console MAYBE_UNUSED)
14401461 fflush (stderr );
14411462 }
14421463
1464+ if (detach_console ) {
14431465#ifdef GIT_WINDOWS_NATIVE
1444- if (detach_console )
14451466 FreeConsole ();
1467+ #else
1468+ /*
1469+ * Create a new session so that the daemon is detached
1470+ * from the parent's process group. This prevents
1471+ * shells with job control (e.g. bash with "set -m")
1472+ * from waiting on the daemon when they wait for a
1473+ * foreground command that implicitly spawned it.
1474+ */
1475+ if (setsid () == -1 )
1476+ warning_errno (_ ("setsid failed" ));
14461477#endif
1478+ }
14471479
14481480 return !!fsmonitor_run_daemon ();
14491481}
@@ -1506,6 +1538,7 @@ static int try_to_start_background_daemon(void)
15061538 cp .no_stdin = 1 ;
15071539 cp .no_stdout = 1 ;
15081540 cp .no_stderr = 1 ;
1541+ cp .close_fd_above_stderr = 1 ;
15091542
15101543 sbgr = start_bg_command (& cp , bg_wait_cb , NULL ,
15111544 fsmonitor__start_timeout_sec );
0 commit comments