From f0c39bdf5117d8f7dd5092033971d7f700bd22dc Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 31 Oct 2014 10:37:56 -0700 Subject: [PATCH] API: fix bug where app doesn't exit if client dies while app in critical section There were two parts to this: - In the timer thread, we need to check for client death even if we're in a critical section. If both conditions hold, set the no_heartbeat status flag. - In boinc_end_critical_section(), check no_heartbeat and exit if set. Also: the various checks in boinc_end_critical_section() (quit, abort, no heartbeat) should be conditioned on options.direct_process_action. Otherwise wrappers that use critical sections won't do the right thing. --- api/boinc_api.cpp | 20 ++++++++++++-------- api/boinc_api.h | 1 + 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/api/boinc_api.cpp b/api/boinc_api.cpp index 887e1f258d..53dcd6e35b 100644 --- a/api/boinc_api.cpp +++ b/api/boinc_api.cpp @@ -1179,18 +1179,19 @@ static void timer_handler() { // see if the client has died, which means we need to die too // (unless we're in a critical section) // - if (in_critical_section==0 && options.check_heartbeat) { + if (options.check_heartbeat) { if (client_dead()) { fprintf(stderr, "%s timer handler: client dead, exiting\n", boinc_msg_prefix(buf, sizeof(buf)) ); - if (options.direct_process_action) { + if (options.direct_process_action && !in_critical_section) { exit_from_timer_thread(0); } else { boinc_status.no_heartbeat = true; } } } + // don't bother reporting CPU time etc. if we're suspended // if (options.send_status_msgs && !boinc_status.suspended) { @@ -1428,13 +1429,16 @@ void boinc_end_critical_section() { // See if we got suspend/quit/abort while in critical section, // and handle them here. // - if (boinc_status.quit_request) { - boinc_exit(0); - } - if (boinc_status.abort_request) { - boinc_exit(EXIT_ABORTED_BY_CLIENT); - } if (options.direct_process_action) { + if (boinc_status.no_heartbeat) { + boinc_exit(0); + } + if (boinc_status.quit_request) { + boinc_exit(0); + } + if (boinc_status.abort_request) { + boinc_exit(EXIT_ABORTED_BY_CLIENT); + } acquire_mutex(); if (suspend_request) { suspend_request = false; diff --git a/api/boinc_api.h b/api/boinc_api.h index 55216f7f24..003ee5b609 100644 --- a/api/boinc_api.h +++ b/api/boinc_api.h @@ -56,6 +56,7 @@ typedef struct BOINC_OPTIONS { // if heartbeat fail, or get process control msg, take // direction action (exit, suspend, resume). // Otherwise just set flag in BOINC status + // This is true for regular apps, false for wrappers int multi_thread; // set this if application creates threads in main process int multi_process;