1616#include "fsmonitor--daemon.h"
1717
1818#include "simple-ipc.h"
19- #include "khash .h"
19+ #include "strmap .h"
2020#include "run-command.h"
2121#include "trace.h"
2222#include "trace2.h"
@@ -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 );
@@ -653,8 +674,6 @@ static int fsmonitor_parse_client_token(const char *buf_token,
653674 return 0 ;
654675}
655676
656- KHASH_INIT (str , const char * , int , 0 , kh_str_hash_func , kh_str_hash_equal )
657-
658677static int do_handle_client (struct fsmonitor_daemon_state * state ,
659678 const char * command ,
660679 ipc_server_reply_cb * reply ,
@@ -671,8 +690,7 @@ static int do_handle_client(struct fsmonitor_daemon_state *state,
671690 const struct fsmonitor_batch * batch ;
672691 struct fsmonitor_batch * remainder = NULL ;
673692 intmax_t count = 0 , duplicates = 0 ;
674- kh_str_t * shown ;
675- int hash_ret ;
693+ struct strset shown = STRSET_INIT ;
676694 int do_trivial = 0 ;
677695 int do_flush = 0 ;
678696 int do_cookie = 0 ;
@@ -861,14 +879,14 @@ static int do_handle_client(struct fsmonitor_daemon_state *state,
861879 * so walk the batch list backwards from the current head back
862880 * to the batch (sequence number) they named.
863881 *
864- * We use khash to de-dup the list of pathnames.
882+ * We use a strset to de-dup the list of pathnames.
865883 *
866884 * NEEDSWORK: each batch contains a list of interned strings,
867885 * so we only need to do pointer comparisons here to build the
868886 * hash table. Currently, we're still comparing the string
869887 * values.
870888 */
871- shown = kh_init_str ( );
889+ strset_init_with_options ( & shown , NULL , 0 );
872890 for (batch = batch_head ;
873891 batch && batch -> batch_seq_nr > requested_oldest_seq_nr ;
874892 batch = batch -> next ) {
@@ -878,11 +896,9 @@ static int do_handle_client(struct fsmonitor_daemon_state *state,
878896 const char * s = batch -> interned_paths [k ];
879897 size_t s_len ;
880898
881- if (kh_get_str ( shown , s ) != kh_end ( shown ))
899+ if (! strset_add ( & shown , s ))
882900 duplicates ++ ;
883901 else {
884- kh_put_str (shown , s , & hash_ret );
885-
886902 trace_printf_key (& trace_fsmonitor ,
887903 "send[%" PRIuMAX "]: %s" ,
888904 count , s );
@@ -909,8 +925,6 @@ static int do_handle_client(struct fsmonitor_daemon_state *state,
909925 total_response_len += payload .len ;
910926 }
911927
912- kh_release_str (shown );
913-
914928 pthread_mutex_lock (& state -> main_lock );
915929
916930 if (token_data -> client_ref_count > 0 )
@@ -954,6 +968,7 @@ static int do_handle_client(struct fsmonitor_daemon_state *state,
954968 trace2_data_intmax ("fsmonitor" , the_repository , "response/count/duplicates" , duplicates );
955969
956970cleanup :
971+ strset_clear (& shown );
957972 strbuf_release (& response_token );
958973 strbuf_release (& requested_token_id );
959974 strbuf_release (& payload );
@@ -1405,6 +1420,15 @@ static int fsmonitor_run_daemon(void)
14051420done :
14061421 pthread_cond_destroy (& state .cookies_cond );
14071422 pthread_mutex_destroy (& state .main_lock );
1423+ {
1424+ struct hashmap_iter iter ;
1425+ struct fsmonitor_cookie_item * cookie ;
1426+
1427+ hashmap_for_each_entry (& state .cookies , & iter , cookie , entry )
1428+ free (cookie -> name );
1429+ hashmap_clear_and_free (& state .cookies ,
1430+ struct fsmonitor_cookie_item , entry );
1431+ }
14081432 fsm_listen__dtor (& state );
14091433 fsm_health__dtor (& state );
14101434
@@ -1420,7 +1444,7 @@ static int fsmonitor_run_daemon(void)
14201444 return err ;
14211445}
14221446
1423- static int try_to_run_foreground_daemon (int detach_console MAYBE_UNUSED )
1447+ static int try_to_run_foreground_daemon (int detach_console )
14241448{
14251449 /*
14261450 * Technically, we don't need to probe for an existing daemon
@@ -1440,10 +1464,21 @@ static int try_to_run_foreground_daemon(int detach_console MAYBE_UNUSED)
14401464 fflush (stderr );
14411465 }
14421466
1467+ if (detach_console ) {
14431468#ifdef GIT_WINDOWS_NATIVE
1444- if (detach_console )
14451469 FreeConsole ();
1470+ #else
1471+ /*
1472+ * Create a new session so that the daemon is detached
1473+ * from the parent's process group. This prevents
1474+ * shells with job control (e.g. bash with "set -m")
1475+ * from waiting on the daemon when they wait for a
1476+ * foreground command that implicitly spawned it.
1477+ */
1478+ if (setsid () == -1 )
1479+ warning_errno (_ ("setsid failed" ));
14461480#endif
1481+ }
14471482
14481483 return !!fsmonitor_run_daemon ();
14491484}
@@ -1506,6 +1541,7 @@ static int try_to_start_background_daemon(void)
15061541 cp .no_stdin = 1 ;
15071542 cp .no_stdout = 1 ;
15081543 cp .no_stderr = 1 ;
1544+ cp .close_fd_above_stderr = 1 ;
15091545
15101546 sbgr = start_bg_command (& cp , bg_wait_cb , NULL ,
15111547 fsmonitor__start_timeout_sec );
0 commit comments