Trying to fix the segfault reported by Alexander Inyukhin in the mailing list:
authorviric <viriketo@gmail.com>
Thu, 09 May 2013 21:41:26 +0200
changeset 333 4a2f6bdca101
parent 332 03801843d725
child 334 e9e212846a89
Trying to fix the segfault reported by Alexander Inyukhin in the mailing list: > When a job is started with -nf flag and another ts instance > is waiting for that job with -w, then the main ts daemon triggers > a null address access after the job finishes. I store temporarily those kind of jobs in the finished list while there are notifiers for them.
jobs.c
--- a/jobs.c	Sat May 26 17:04:31 2012 +0200
+++ b/jobs.c	Thu May 09 21:41:26 2013 +0200
@@ -627,6 +627,21 @@
     return job_is_in_state(jobid, HOLDING_CLIENT);
 }
 
+static int in_notify_list(int jobid)
+{
+    struct Notify *n, *tmp;
+
+    n = first_notify;
+    while (n != 0)
+    {
+        tmp = n;
+        n = n->next;
+        if (tmp->jobid == jobid)
+            return 1;
+    }
+    return 0;
+}
+
 void job_finished(const struct Result *result, int jobid)
 {
     struct Job *p;
@@ -681,8 +696,8 @@
             }
         }
 
-        /* Add it to the finished queue */
-        if (p->should_keep_finished)
+        /* Add it to the finished queue (maybe temporarily) */
+        if (p->should_keep_finished || in_notify_list(p->jobid))
             new_finished_job(p);
 
         /* Remove it from the run queue */
@@ -1095,6 +1110,34 @@
     free(n);
 }
 
+static void destroy_finished_job(struct Job *j)
+{
+    if (j == first_finished_job)
+        first_finished_job = j->next;
+    else
+    {
+        struct Job *i;
+        for(i = first_finished_job; i != 0; ++i)
+        {
+            if (i->next == j)
+            {
+                i->next = j->next;
+                break;
+            }
+        }
+        if (i == 0) {
+            error("Cannot destroy the expected job %i", j->jobid);
+        }
+    }
+
+    free(j->notify_errorlevel_to);
+    free(j->command);
+    free(j->output_filename);
+    pinfo_free(&j->info);
+    free(j->label);
+    free(j);
+}
+
 /* This is called when a job finishes */
 void check_notify_list(int jobid)
 {
@@ -1118,6 +1161,12 @@
                  * removes the element from the linked list, we can
                  * safely follow on the list from n->next. */
                 s_remove_notification(tmp->socket);
+
+                /* Remove the jobs that were temporarily in the finished list,
+                 * just for their notifiers. */
+                if (!in_notify_list(jobid) && !j->should_keep_finished) {
+                    destroy_finished_job(j);
+                }
             }
         }
     }