Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Remove debugging fprintf
[simgrid.git] / tools / tesh / run_context.c
index e809ebe..181b688 100644 (file)
@@ -85,7 +85,7 @@ void rctx_init(void)
   sigwaiter_cond = xbt_os_cond_init();
   xbt_os_mutex_acquire(sigwaiter_mutex);
   sigwaiter_thread = xbt_os_thread_create("Armaggedon request waiter",
-                                          armageddon_sigwaiter, NULL);
+                                          armageddon_sigwaiter, NULL, NULL);
   /* Wait for thread to start... */
   xbt_os_cond_wait(sigwaiter_cond, sigwaiter_mutex);
   xbt_os_mutex_release(sigwaiter_mutex);
@@ -101,21 +101,11 @@ void rctx_init(void)
 void rctx_exit(void)
 {
   int i;
-  if (bg_jobs) {
-    /* Do not use xbt_dynar_free or it will lock the dynar, preventing armageddon from working */
-    while (xbt_dynar_length(bg_jobs)) {
-      rctx_t rctx = xbt_dynar_getlast_as(bg_jobs, rctx_t);
-      wait_it(rctx);
-      xbt_dynar_pop(bg_jobs, &rctx);
-      rctx_free(rctx);
-    }
-  }
   for (i = 0; i < 3; i++)
     sigaction(oldact[i].num, &oldact[i].act, NULL);
   xbt_os_cond_signal(sigwaiter_cond);
   xbt_os_thread_join(sigwaiter_thread, NULL);
-  if (bg_jobs)
-    xbt_dynar_free(&bg_jobs);
+  xbt_dynar_free(&bg_jobs);
   xbt_os_cond_destroy(sigwaiter_cond);
   xbt_os_mutex_destroy(sigwaiter_mutex);
   xbt_os_mutex_destroy(armageddon_mutex);
@@ -123,17 +113,15 @@ void rctx_exit(void)
 
 void rctx_wait_bg(void)
 {
-  if (bg_jobs) {
-    /* Do not use xbt_dynar_free or it will lock the dynar, preventing armageddon from working */
-    while (xbt_dynar_length(bg_jobs)) {
-      rctx_t rctx = xbt_dynar_getlast_as(bg_jobs, rctx_t);
-      wait_it(rctx);
-      xbt_dynar_pop(bg_jobs, &rctx);
-      rctx_free(rctx);
-    }
-    xbt_dynar_free(&bg_jobs);
+  /* Do not use xbt_dynar_free or it will lock the dynar, preventing armageddon
+   * from working */
+  while (xbt_dynar_length(bg_jobs)) {
+    rctx_t rctx = xbt_dynar_getlast_as(bg_jobs, rctx_t);
+    wait_it(rctx);
+    xbt_dynar_pop(bg_jobs, &rctx);
+    rctx_free(rctx);
   }
-  bg_jobs = xbt_dynar_new_sync(sizeof(rctx_t), kill_it);
+  xbt_dynar_reset(bg_jobs);
 }
 
 static void rctx_armageddon_kill_one(rctx_t initiator, const char *filepos,
@@ -180,6 +168,13 @@ void rctx_armageddon(rctx_t initiator, int exitcode)
     rctx_armageddon_kill_one(initiator, filepos, job);
   }
 
+  /* Give runner threads a chance to acknowledge the processes deaths */
+  usleep(10000);
+  /* Ensure that nobody is running rctx_wait on exit */
+  if (fg_job)
+    xbt_os_mutex_acquire(rctx->interruption);
+  xbt_dynar_foreach(bg_jobs, cursor, job)
+    xbt_os_mutex_acquire(job->interruption);
   VERB0("Shut everything down!");
   exit(exitcode);
 }
@@ -216,6 +211,7 @@ void rctx_empty(rctx_t rc)
   rc->is_background = 0;
   rc->is_stoppable = 0;
   rc->output = e_output_check;
+  rc->output_sort = 0;
   rc->brokenpipe = 0;
   rc->timeout = 0;
   rc->interrupted = 0;
@@ -230,6 +226,7 @@ rctx_t rctx_new()
   rctx_t res = xbt_new0(s_rctx_t, 1);
 
   res->input = xbt_strbuff_new();
+  res->output_sort = 0;
   res->output_wanted = xbt_strbuff_new();
   res->output_got = xbt_strbuff_new();
   res->interruption = xbt_os_mutex_init();
@@ -344,6 +341,13 @@ void rctx_pushline(const char *filepos, char kind, char *line)
       VERB2("[%s] (next command must return code %d)",
             filepos, rctx->expected_return);
 
+    } else if (!strncmp(line, "output sort", strlen("output sort"))) {
+      sort_len = atoi(line + strlen("output sort"));
+      if (sort_len==0)
+        sort_len=SORT_LEN_DEFAULT;
+      rctx->output_sort = 1;
+      VERB1("[%s] (sort output of next command)", filepos);
+
     } else if (!strncmp(line, "output ignore", strlen("output ignore"))) {
       rctx->output = e_output_ignore;
       VERB1("[%s] (ignore output of next command)", filepos);
@@ -597,9 +601,9 @@ void rctx_start(void)
 
     rctx->reader_done = 0;
     rctx->reader =
-        xbt_os_thread_create("reader", thread_reader, (void *) rctx);
+        xbt_os_thread_create("reader", thread_reader, (void *) rctx, NULL);
     rctx->writer =
-        xbt_os_thread_create("writer", thread_writer, (void *) rctx);
+        xbt_os_thread_create("writer", thread_writer, (void *) rctx, NULL);
 
   } else {                      /* child */
     close(child_in[1]);
@@ -630,7 +634,7 @@ void rctx_start(void)
     DEBUG2("RCTX: new bg=%p, new fg=%p", old, rctx);
 
     DEBUG2("Launch a thread to wait for %s %d", old->cmd, old->pid);
-    runner = xbt_os_thread_create(old->cmd, rctx_wait, (void *) old);
+    runner = xbt_os_thread_create(old->cmd, rctx_wait, (void *) old, NULL);
     old->runner = runner;
     VERB3("Launched thread %p to wait for %s %d", runner, old->cmd,
           old->pid);
@@ -639,6 +643,23 @@ void rctx_start(void)
   }
 }
 
+/* Helper function to sort the output */
+static int cmpstringp(const void *p1, const void *p2) {
+  /* Sort only using the 19 first chars (date+pid)
+   * If the dates are the same, then, sort using pointer address (be stable wrt output of each process)
+   */
+  const char *s1 = *((const char**) p1);
+  const char *s2 = *((const char**) p2);
+
+  DEBUG2("Compare strings '%s' and '%s'", s1, s2);
+
+  int res = strncmp(s1, s2, sort_len);
+  if (res == 0)
+    return p1>p2;
+  return res;
+}
+
+
 /* Waits for the child to end (or to timeout), and check its
    ending conditions. This is launched from rctx_start but either in main
    thread (for foreground jobs) or in a separate one for background jobs.
@@ -772,6 +793,19 @@ void *rctx_wait(void *r)
     errcode = 1;
   }
 
+  if (rctx->output_sort) {
+    xbt_dynar_t a = xbt_str_split(rctx->output_got->data, "\n");
+    xbt_dynar_sort(a,cmpstringp);
+    char *sorted_output = xbt_str_join(a, "\n");
+    strcpy(rctx->output_got->data, sorted_output);
+    xbt_free(sorted_output);
+    xbt_dynar_free(&a);
+    /* If an empty line moved in first position, move it back to the end */
+    if (rctx->output_got->data[0]=='\n') {
+      memmove(rctx->output_got->data,rctx->output_got->data+1,rctx->output_got->used-1);
+      rctx->output_got->data[rctx->output_got->used-1] = '\n';
+    }
+  }
   if ((errcode && errcode != 1) || rctx->interrupted) {
     /* checking output, and matching */
     xbt_dynar_t a = xbt_str_split(rctx->output_got->data, "\n");