diff -ruN src/trackerd/trackerd.c src/trackerd/trackerd.c --- src/trackerd/trackerd.c 2006-08-22 11:38:42.000000000 +0200 +++ src/trackerd/trackerd.c 2006-08-24 20:17:53.000000000 +0200 @@ -64,6 +64,8 @@ static DBusConnection *main_connection; DBConnection *main_thread_db_con; +static GMutex *signal_handler_mutex = NULL; +static GThread *signal_handler_thread = NULL; static gboolean shutdown = FALSE; /* @@ -141,27 +143,20 @@ static gboolean do_cleanup () { - tracker_print_object_allocations (); tracker_log ("starting shutdown..."); shutdown = TRUE; - - - /* clear pending files and watch tables*/ - tracker_db_clear_temp (main_thread_db_con); - - /* stop threads from further processing of events if possible */ - tracker_dbus_shutdown (main_connection); //tracker_indexer_close (file_indexer); tracker_log ("shutting down threads"); + /* send signals to each thread to wake them up and then stop them */ g_mutex_lock (tracker->poll_signal_mutex); @@ -172,6 +167,15 @@ g_cond_signal (tracker->request_thread_signal); g_mutex_unlock (tracker->request_signal_mutex); + /* any watching on files has to finish */ + g_mutex_lock (tracker->is_watching_mutex); + + /* clear pending files and watch tables*/ + tracker_db_clear_temp (main_thread_db_con); + + + /* then continue to send signals... */ + g_mutex_lock (tracker->metadata_signal_mutex); g_cond_signal (tracker->metadata_thread_signal); g_mutex_unlock (tracker->metadata_signal_mutex); @@ -196,15 +200,15 @@ g_mutex_lock (tracker->files_stopped_mutex); tracker_db_close (main_thread_db_con); - + /* This must be called after all other db functions */ tracker_db_finalize (); - + tracker_log ("shutting down main thread"); + g_main_loop_quit (tracker->loop); - exit (EXIT_SUCCESS); - return FALSE; + return TRUE; } static int @@ -491,35 +495,42 @@ } -static void -signal_handler (int signo) +static gboolean +signal_handler (void) { - - if (!tracker->is_running) return; + for (;;) { + sigset_t signal_set; + int signo; + + /* set to wait any signal */ + sigfillset (&signal_set); + sigwait (&signal_set, &signo); - static gboolean in_loop = FALSE; + /* XXX: perhaps it could be a way to handle very early sended signals? */ + if (!tracker->is_running) { + continue; + } - /* avoid re-entrant signals handler calls */ - if (in_loop) return; - - in_loop = TRUE; - - switch (signo) { + /* only one signal at time */ + g_mutex_lock (signal_handler_mutex); - case SIGSEGV: + switch (signo) { + + case SIGSEGV: case SIGBUS: case SIGILL: case SIGFPE: case SIGPIPE: case SIGABRT: if (tracker->log_file) { - tracker_log ("Received fatal signal %s so now aborting.",g_strsignal (signo)); + tracker_log ("Received fatal signal %s so now aborting.", g_strsignal (signo)); } tracker->is_running = FALSE; + tracker->is_exit_success = FALSE; tracker_end_watching (); - do_cleanup (); - exit (1); - break; + do_cleanup (); + g_mutex_unlock (signal_handler_mutex); + return TRUE; case SIGTERM: case SIGINT: @@ -528,23 +539,19 @@ } tracker->is_running = FALSE; tracker_end_watching (); - g_timeout_add_full (G_PRIORITY_LOW, - 500, - (GSourceFunc) do_cleanup, - NULL, NULL - ); - - break; - - + tracker->is_exit_success = TRUE; + do_cleanup (); + g_mutex_unlock (signal_handler_mutex); + return TRUE; default: if (tracker->log_file) { tracker_log ("Received signal %s ", g_strsignal (signo)); } - in_loop = FALSE; - break; - } + g_mutex_unlock (signal_handler_mutex); + } + } + return TRUE; } @@ -821,8 +828,11 @@ { if (!tracker->is_running) return FALSE; + g_mutex_lock (tracker->is_watching_mutex); + if (!tracker_start_watching ()) { tracker_log ("File monitoring failed to start"); + g_mutex_unlock (tracker->is_watching_mutex); do_cleanup (); exit (1); } else { @@ -850,6 +860,8 @@ tracker_log ("waiting for file events..."); } + g_mutex_unlock (tracker->is_watching_mutex); + return FALSE; } @@ -1728,12 +1740,9 @@ main (int argc, char **argv) { int lfp; - struct sigaction act; - sigset_t empty_mask; + sigset_t signal_set; char *prefix, *lock_file, *str, *lock_str, *tracker_data_dir; - - gboolean need_setup = FALSE; DBConnection *db_con; @@ -1756,6 +1765,15 @@ dbus_g_thread_init (); + /* any signal will be trapped then treated in signal_handler() */ + sigfillset (&signal_set); + pthread_sigmask (SIG_BLOCK, &signal_set, NULL); + /* this mutex ensures that just one signal at time will be treated */ + signal_handler_mutex = g_mutex_new (); + signal_handler_thread = g_thread_create ((GThreadFunc) signal_handler, NULL, TRUE, NULL); + + + /* now tracker stuff */ tracker = g_new (Tracker, 1); tracker->watch_directory_roots_list = NULL; @@ -1764,7 +1782,9 @@ tracker->use_nfs_safe_locking = FALSE; tracker->is_running = FALSE; + tracker->is_exit_success = FALSE; + tracker->is_watching_mutex = g_mutex_new (); tracker->poll_access_mutex = g_mutex_new (); tracker->files_check_mutex = g_mutex_new (); @@ -1876,22 +1896,6 @@ } - /* trap signals */ - sigemptyset (&empty_mask); - act.sa_handler = signal_handler; - act.sa_mask = empty_mask; - act.sa_flags = SA_NODEFER; - sigaction (SIGTERM, &act, NULL); - sigaction (SIGILL, &act, NULL); - sigaction (SIGBUS, &act, NULL); - sigaction (SIGFPE, &act, NULL); - sigaction (SIGHUP, &act, NULL); - sigaction (SIGSEGV, &act, NULL); - sigaction (SIGABRT, &act, NULL); - sigaction (SIGUSR1, &act, NULL); - sigaction (SIGINT, &act, NULL); - - tracker_load_config_file (); @@ -2032,18 +2036,13 @@ tracker->file_metadata_thread = g_thread_create ((GThreadFunc) extract_metadata_thread, NULL, TRUE, NULL); tracker->user_request_thread = g_thread_create ((GThreadFunc) process_user_request_queue_thread, NULL, TRUE, NULL); - g_main_loop_run (tracker->loop); - - /* the following should never be reached in practice */ - tracker_log ("we should never get this message"); - - tracker_db_close (db_con); - tracker_db_thread_end (); - - tracker_dbus_shutdown (main_connection); + /* g_main_loop_quit() is (and must be stay) called in do_cleanup() and *only* there! */ + g_main_loop_run (tracker->loop); - do_cleanup (); + /* To be sure that all cleanup is done if something is called after g_main_loop_quit() in do_cleanup(). + After that, there will be only one thread. */ + g_thread_join (signal_handler_thread); - return EXIT_SUCCESS; + return (tracker->is_exit_success ? EXIT_SUCCESS : EXIT_FAILURE); } diff -ruN src/trackerd/tracker-utils.h src/trackerd/tracker-utils.h --- src/trackerd/tracker-utils.h 2006-08-21 22:18:26.000000000 +0200 +++ src/trackerd/tracker-utils.h 2006-08-24 20:17:45.000000000 +0200 @@ -50,6 +50,7 @@ GMutex *scheduler_mutex; gboolean is_running; + gboolean is_exit_success; GMainLoop *loop; GMutex *log_access_mutex; @@ -59,6 +60,7 @@ GAsyncQueue *file_metadata_queue; GAsyncQueue *user_request_queue; + GMutex *is_watching_mutex; GMutex *files_check_mutex; GMutex *metadata_check_mutex; GMutex *request_check_mutex;