Fix signal handler for handling all dead childs 19/127919/3
authorjongmyeongko <jongmyeong.ko@samsung.com>
Tue, 2 May 2017 09:59:35 +0000 (18:59 +0900)
committerjongmyeong ko <jongmyeong.ko@samsung.com>
Mon, 8 May 2017 11:15:23 +0000 (11:15 +0000)
The signal handler can be called once (not for each child)
when childs are terminated at very close timing each other.

reproduce : #pkgcmd --clear-all
this causes all slots (rpm, tpk and wgt) active, and
some processes are terminated at very close timing.

Change-Id: Ie007e17431e78e2920356e6178dff3af86826790
Signed-off-by: jongmyeongko <jongmyeong.ko@samsung.com>
src/pkgmgr-server.c

index 82cb5d5..7f6a2ae 100644 (file)
@@ -193,34 +193,37 @@ static gboolean __signal_handler(GIOChannel *io, GIOCondition cond,
                return TRUE;
        }
 
-       pid = waitpid(-1, &status, WNOHANG);
-       job = (struct backend_job *)g_hash_table_lookup(backend_info_table,
-                       (gconstpointer)pid);
-       if (job == NULL) {
-               ERR("Unknown child exit");
-               return -1;
-       }
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+               job = (struct backend_job *)g_hash_table_lookup(
+                       backend_info_table, (gconstpointer)pid);
+               if (job == NULL) {
+                       ERR("Unknown child exit");
+                       continue;
+               }
 
-       __set_backend_free(job->backend_slot);
-       if (WIFSIGNALED(status)) {
-               _send_fail_signal(job);
-               INFO("backend[%s][%d] exit with signal[%d]", job->backend_type,
-                               pid, WTERMSIG(status));
-       } else if (WEXITSTATUS(status)) {
-               INFO("backend[%s][%d] exit with error", job->backend_type, pid);
-       } else {
-               INFO("backend[%s][%d] exit", job->backend_type, pid);
-       }
+               __set_backend_free(job->backend_slot);
+               if (WIFSIGNALED(status)) {
+                       _send_fail_signal(job);
+                       INFO("backend[%s][%d] exit with signal[%d]",
+                               job->backend_type, pid, WTERMSIG(status));
+               } else if (WEXITSTATUS(status)) {
+                       INFO("backend[%s][%d] exit with error",
+                               job->backend_type, pid);
+               } else {
+                       INFO("backend[%s][%d] exit", job->backend_type, pid);
+               }
 
-       if (job->extra) {
-               if (job->extra->getsize_fifo) {
-                       ERR("invalid backend close");
-                       _return_value_to_caller(job->req_id,
-                               g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
+               if (job->extra) {
+                       if (job->extra->getsize_fifo) {
+                               ERR("invalid backend close");
+                               _return_value_to_caller(job->req_id,
+                                       g_variant_new("(ix)", PKGMGR_R_ERROR,
+                                       -1));
+                       }
                }
-       }
 
-       g_hash_table_remove(backend_info_table, (gconstpointer)pid);
+               g_hash_table_remove(backend_info_table, (gconstpointer)pid);
+       }
        g_idle_add(queue_job, NULL);
 
        return TRUE;