+ xbt_os_cond_destroy(sigwaiter_cond);
+ xbt_os_mutex_destroy(sigwaiter_mutex);
+ xbt_os_mutex_destroy(armageddon_mutex);
+}
+
+void rctx_wait_bg(void)
+{
+ /* Do not use xbt_dynar_free or it will lock the dynar, preventing armageddon
+ * from working */
+ while (!xbt_dynar_is_empty(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_reset(bg_jobs);
+}
+
+static void rctx_armageddon_kill_one(rctx_t initiator, const char *filepos,
+ rctx_t rctx)
+{
+ if (rctx != initiator) {
+ XBT_INFO("Kill <%s> because <%s> failed", rctx->filepos, filepos);
+ xbt_os_mutex_acquire(rctx->interruption);
+ if (!rctx->reader_done) {
+ rctx->interrupted = 1;
+ kill(rctx->pid, SIGTERM);
+ struct timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = (100e-6 - floor(100e-6)) * 1e9;
+ nanosleep (&ts, NULL);
+ kill(rctx->pid, SIGKILL);
+ }
+ xbt_os_mutex_release(rctx->interruption);
+ }
+}
+
+void rctx_armageddon(rctx_t initiator, int exitcode)
+{
+ unsigned int cursor;
+ rctx_t job;
+ const char *filepos = initiator && initiator->filepos ?
+ initiator->filepos : "(master)";
+
+ XBT_DEBUG("Armageddon request by <%s> (exit=%d)", filepos, exitcode);
+ xbt_os_mutex_acquire(armageddon_mutex);
+ if (armageddon_initiator != NULL) {
+ XBT_VERB("Armageddon already started. Let it go");
+ xbt_os_mutex_release(armageddon_mutex);
+ return;
+ }
+ XBT_DEBUG("Armageddon request by <%s> got the lock. Let's go amok",
+ filepos);
+ armageddon_initiator = initiator;
+ xbt_os_mutex_release(armageddon_mutex);
+
+ /* Kill foreground command */
+ if (fg_job)
+ rctx_armageddon_kill_one(initiator, filepos, rctx);
+
+ /* Kill any background commands */
+ xbt_dynar_foreach(bg_jobs, cursor, job) {
+ rctx_armageddon_kill_one(initiator, filepos, job);
+ }
+
+ /* Give runner threads a chance to acknowledge the processes deaths */
+ struct timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = (10000e-6 - floor(10000e-6)) * 1e9;
+ nanosleep (&ts, NULL);
+ /* 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);
+ XBT_VERB("Shut everything down!");
+ exit(exitcode);