diff --git a/api/boinc_api.C b/api/boinc_api.C index 597229e841..6c462d4dd7 100644 --- a/api/boinc_api.C +++ b/api/boinc_api.C @@ -81,6 +81,7 @@ extern BOOL win_loop_done; LONG CALLBACK boinc_catch_signal(EXCEPTION_POINTERS *ExceptionInfo); #else extern void boinc_catch_signal(int signal); +extern void boinc_quit(int sig); #endif static APP_INIT_DATA aid; @@ -88,11 +89,9 @@ GRAPHICS_INFO gi; static double timer_period = 1.0/50.0; // 50 Hz timer static double time_until_checkpoint; static double time_until_fraction_done_update; -static double time_until_quit_check; static double fraction_done; static double last_checkpoint_cpu_time; static bool ready_to_checkpoint = false; -static bool check_quit = false; static bool write_frac_done = false; static bool this_process_active; static bool time_to_quit = false; @@ -161,7 +160,6 @@ int boinc_init() { #endif time_until_checkpoint = aid.checkpoint_period; time_until_fraction_done_update = aid.fraction_done_update_period; - time_until_quit_check = 1; // check every 1 second for quit request from core client this_process_active = true; boinc_install_signal_handlers(); @@ -177,7 +175,7 @@ int boinc_install_signal_handlers() { #ifdef HAVE_SIGNAL_H signal( SIGHUP, boinc_catch_signal ); // terminal line hangup signal( SIGINT, boinc_catch_signal ); // interrupt program - signal( SIGQUIT, boinc_catch_signal ); // quit program + signal( SIGQUIT, boinc_quit ); // quit program signal( SIGILL, boinc_catch_signal ); // illegal instruction signal( SIGABRT, boinc_catch_signal ); // abort(2) call signal( SIGBUS, boinc_catch_signal ); // bus error @@ -244,7 +242,6 @@ void boinc_catch_signal(int signal) { switch(signal) { case SIGHUP: fprintf( stderr, "SIGHUP: terminal line hangup" ); break; case SIGINT: fprintf( stderr, "SIGINT: interrupt program" ); break; - case SIGQUIT: fprintf( stderr, "SIGQUIT: quit program" ); break; case SIGILL: fprintf( stderr, "SIGILL: illegal instruction" ); break; case SIGABRT: fprintf( stderr, "SIGABRT: abort called" ); break; case SIGBUS: fprintf( stderr, "SIGBUS: bus error" ); break; @@ -256,6 +253,11 @@ void boinc_catch_signal(int signal) { fprintf( stderr, "\nExiting...\n" ); exit(ERR_SIGNAL_CATCH); } + +void boinc_quit(int sig) { + signal( SIGQUIT, boinc_quit ); // reset signal + time_to_quit = true; +} #endif int boinc_finish(int status) { @@ -306,15 +308,16 @@ int boinc_resolve_filename(char *virtual_name, char *physical_name, int len) { } bool boinc_time_to_checkpoint() { - if (check_quit) { - FILE* f = fopen(QUIT_FILE, "r"); - if(f) { - parse_quit_file(f,time_to_quit); - fclose(f); - } - time_until_quit_check = 1; // reset to 1 second - check_quit = false; +#ifdef _WIN32 + DWORD eventState; + // Check if core client has requested us to exit + WaitForSingleObject(quitRequestEvent, 0L); + + switch (eventState) { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: } +#endif if (write_frac_done) { write_fraction_done_file(fraction_done, boinc_cpu_time(), last_checkpoint_cpu_time); @@ -435,13 +438,6 @@ void on_timer(int a) { } } - if (!check_quit) { - time_until_quit_check -= timer_period; - if (time_until_quit_check <= 0) { - check_quit = true; - } - } - if (!write_frac_done && this_process_active) { time_until_fraction_done_update -= timer_period; if (time_until_fraction_done_update <= 0) { @@ -592,21 +588,6 @@ int parse_fraction_done_file(FILE* f, double& pct, double& cpu, double& checkpoi return 0; } -int write_quit_file(FILE* f) { - fprintf(f, "\n"); - return 0; -} - -int parse_quit_file(FILE* f, bool& quit) { - char buf[256]; - - while (fgets(buf, 256, f)) { - if (match_tag(buf, "")) quit = true; - else fprintf(stderr, "parse_quit_file: unrecognized %s", buf); - } - return 0; -} - // TODO: this should handle arbitrarily many fd/filename pairs. // Also, give the tags better names int write_fd_init_file(FILE* f, char *file_name, int fdesc, int input_file ) { diff --git a/api/boinc_api.h b/api/boinc_api.h index a678a37ed7..aaf27ba9be 100755 --- a/api/boinc_api.h +++ b/api/boinc_api.h @@ -84,15 +84,12 @@ int write_fd_init_file(FILE*, char*, int, int); int parse_fd_init_file(FILE*); int write_fraction_done_file(double, double, double); int parse_fraction_done_file(FILE*, double&, double&, double&); -int write_quit_file(FILE* f); -int parse_quit_file(FILE* f, bool& quit); #define INIT_DATA_FILE "init_data.xml" #define GRAPHICS_DATA_FILE "graphics.xml" #define FD_INIT_FILE "fd_init.xml" #define FRACTION_DONE_FILE "fraction_done.xml" #define FRACTION_DONE_TEMP_FILE "fraction_done.tmp" -#define QUIT_FILE "quit.xml" #define STDERR_FILE "stderr.txt" int set_timer(double period); diff --git a/client/app.C b/client/app.C index 768e4b1a0f..289a7867ff 100644 --- a/client/app.C +++ b/client/app.C @@ -266,12 +266,10 @@ int ACTIVE_TASK::start(bool first_time) { fclose(f); - sprintf(temp, "%s%s%s", slot_dir, PATH_SEPARATOR, QUIT_FILE); - file_delete(temp); - #ifdef _WIN32 PROCESS_INFORMATION process_info; STARTUPINFO startup_info; + SECURITY_ATTRIBUTES quit_handle_attrs; char slotdirpath[256]; char cmd_line[512]; int win_error; @@ -282,6 +280,11 @@ int ACTIVE_TASK::start(bool first_time) { startup_info.lpReserved = NULL; startup_info.lpDesktop = ""; + quit_handle_attrs.nLength = sizeof(SECURITY_ATTRIBUTES); + quit_handle_attrs.lpSecurityDescriptor = NULL; + quit_handle_attrs.bInheritHandle = TRUE; + quitRequestEvent = CreateEvent( &quit_handle_attrs, FALSE, FALSE, + // NOTE: in Windows, stderr is redirected within boinc_init(); sprintf( cmd_line, "%s %s", exec_path, wup->command_line ); @@ -360,23 +363,16 @@ int ACTIVE_TASK::start(bool first_time) { // If it doesn't exit within a set time (seconds), the process is terminated // int ACTIVE_TASK::request_exit() { - char quit_file[256]; - int retval; - - get_slot_dir(slot, slot_dir); - sprintf(quit_file, "%s%s%s", slot_dir, PATH_SEPARATOR, QUIT_FILE); - FILE *fp = fopen(quit_file, "w"); - if (!fp) return ERR_FOPEN; - retval = write_quit_file(fp); - fclose(fp); - if (retval) return retval; - return 0; +#ifdef _WIN32 + return !SetEvent(quitRequestEvent); +#else + return kill(pid, SIGQUIT); +#endif } int ACTIVE_TASK::kill_task() { #ifdef _WIN32 - TerminateProcess(pid_handle, -1); - return 0; + return !TerminateProcess(pid_handle, -1); #else return kill(pid, SIGKILL); #endif @@ -464,6 +460,7 @@ bool ACTIVE_TASK_SET::poll() { } CloseHandle(atp->pid_handle); CloseHandle(atp->thread_handle); + CloseHandle(atp->quitRequestEvent); atp->read_stderr_file(); clean_out_dir(atp->slot_dir); } diff --git a/client/app.h b/client/app.h index 002a671bb3..a4b7f6aa27 100644 --- a/client/app.h +++ b/client/app.h @@ -54,7 +54,7 @@ typedef int PROCESS_ID; class ACTIVE_TASK { public: #ifdef _WIN32 - HANDLE pid_handle,thread_handle; + HANDLE pid_handle, thread_handle, quitRequestEvent; #endif RESULT* result; WORKUNIT* wup; diff --git a/client/cs_apps.C b/client/cs_apps.C index 63e6ba18dc..e06e565f73 100644 --- a/client/cs_apps.C +++ b/client/cs_apps.C @@ -51,7 +51,7 @@ int CLIENT_STATE::cleanup_and_exit() { // don't return here - we'll exit anyway } retval = write_state_file(); - if (retval) { + if (retval) { fprintf(stderr, "error: CLIENT_STATE.exit: write_state_file failed\n"); // don't return here - we'll exit anyway }