diff --git a/checkin_notes b/checkin_notes index c952a953e7..e4cce741b2 100755 --- a/checkin_notes +++ b/checkin_notes @@ -6901,3 +6901,21 @@ David 18 Oct 2003 cs_statefile.C (new) main.C maybe_gui.h (removed) + +David 18 Oct 2003 + - When reset (or detach from) a process, wait for running applications to exit + before doing other things (e.g., deleting files, + which will fail is processes have them open) + Implementation: exit_tasks() etc. now take a PROJECT* arg + - When a master file fetch fails on a tentative project (e.g. bad URL) + avoid a situation where we remove the HTTP_OP, + then detach_project() tries to remove it a second time + - print messages when reset/detach + + client/ + app.C,h + client_state.C,h + prefs.C + scheduler_op.C + win/ + wingui.h diff --git a/client/app.C b/client/app.C index 8882bcdc0a..34a47505e2 100644 --- a/client/app.C +++ b/client/app.C @@ -759,8 +759,10 @@ bool ACTIVE_TASK_SET::check_rsc_limits_exceeded() { return false; } -// The application has done something wrong. -// May as well send it a kill signal. +// If process is running, send it a kill signal +// This is done when +// 1) project is reset or detached +// 2) app has exceeded CPU, disk, or mem limits // int ACTIVE_TASK::abort() { if (state == PROCESS_RUNNING) { @@ -811,37 +813,42 @@ void ACTIVE_TASK::check_graphics_mode_ack() { } } -// send quit signal to all tasks. -// If they don't exit in one second, send them a kill signal +// send quit signal to all tasks in the project +// (or all tasks, if zero). +// If they don't exit in 5, send them a kill signal +// and wait up to 5 more seconds to exit. // TODO: unsuspend active tasks so they have a chance to checkpoint // -int ACTIVE_TASK_SET::exit_tasks() { - request_tasks_exit(); +int ACTIVE_TASK_SET::exit_tasks(PROJECT* proj) { + request_tasks_exit(proj); // Wait 5 seconds for them to exit normally; if they don't then kill them // - if (wait_for_exit(5)) { - kill_tasks(); + if (wait_for_exit(5, proj)) { + kill_tasks(proj); } + wait_for_exit(5, proj); get_cpu_times(); return 0; } -// Wait up to wait_time seconds for all processes to exit +// Wait up to wait_time seconds for processes to exit +// If proj is zero, wait for all processes, else that project's +// NOTE: it's bad form to sleep, but it would be complex to avoid it here // -int ACTIVE_TASK_SET::wait_for_exit(double wait_time) { +int ACTIVE_TASK_SET::wait_for_exit(double wait_time, PROJECT* proj) { bool all_exited; unsigned int i,n; ACTIVE_TASK *atp; for (i=0; i<10; i++) { - boinc_sleep(wait_time/10.0); all_exited = true; for (n=0; nwup->project != proj) continue; if (!atp->task_exited()) { all_exited = false; break; @@ -849,11 +856,29 @@ int ACTIVE_TASK_SET::wait_for_exit(double wait_time) { } if (all_exited) return 0; + boinc_sleep(wait_time/10.0); } return -1; } +int ACTIVE_TASK_SET::abort_project(PROJECT* project) { + vector::iterator task_iter; + ACTIVE_TASK* atp; + + exit_tasks(project); + task_iter = active_tasks.begin(); + while (task_iter != active_tasks.end()) { + atp = *task_iter; + if (atp->result->project == project) { + task_iter = active_tasks.erase(task_iter); + } else { + task_iter++; + } + } + return 0; +} + // Find the ACTIVE_TASK in the current set with the matching PID // ACTIVE_TASK* ACTIVE_TASK_SET::lookup_pid(int pid) { @@ -917,11 +942,12 @@ void ACTIVE_TASK_SET::unsuspend_all() { // Send quit signal to all currently running tasks // -void ACTIVE_TASK_SET::request_tasks_exit() { +void ACTIVE_TASK_SET::request_tasks_exit(PROJECT* proj) { unsigned int i; ACTIVE_TASK *atp; for (i=0; iwup->project != proj) continue; atp->request_exit(); } } @@ -929,11 +955,12 @@ void ACTIVE_TASK_SET::request_tasks_exit() { // Send kill signal to all currently running tasks // Don't wait for them to exit // -void ACTIVE_TASK_SET::kill_tasks() { +void ACTIVE_TASK_SET::kill_tasks(PROJECT* proj) { unsigned int i; ACTIVE_TASK *atp; for (i=0; iwup->project != proj) continue; atp->kill_task(); } } diff --git a/client/app.h b/client/app.h index cc7107eae4..d79d21b4e2 100644 --- a/client/app.h +++ b/client/app.h @@ -132,16 +132,17 @@ public: active_tasks_v active_tasks; int insert(ACTIVE_TASK*); int remove(ACTIVE_TASK*); - int wait_for_exit(double); ACTIVE_TASK* lookup_pid(int); ACTIVE_TASK* lookup_result(RESULT*); bool poll(); void suspend_all(); void unsuspend_all(); int restart_tasks(); - void request_tasks_exit(); - int exit_tasks(); - void kill_tasks(); + void request_tasks_exit(PROJECT* p=0); + int wait_for_exit(double, PROJECT* p=0); + int exit_tasks(PROJECT* p=0); + void kill_tasks(PROJECT* p=0); + int abort_project(PROJECT*); void get_cpu_times(); bool check_app_exited(); bool check_rsc_limits_exceeded(); diff --git a/client/client_state.C b/client/client_state.C index be9a3ace38..faf7161783 100644 --- a/client/client_state.C +++ b/client/client_state.C @@ -175,9 +175,11 @@ int CLIENT_STATE::init() { // printing the platform name here helps bug reports because users often // give us this line but don't say what platform they have - msg_printf(NULL, MSG_INFO, "Starting BOINC client version %d.%02d (%s)", - core_client_major_version, core_client_minor_version, platform_name - ); + // + msg_printf( + NULL, MSG_INFO, "Starting BOINC client version %d.%02d (%s)", + core_client_major_version, core_client_minor_version, platform_name + ); // parse account files. // If there are none, prompt user for project URL and create file @@ -931,20 +933,13 @@ int CLIENT_STATE::reset_project(PROJECT* project) { unsigned int i; APP_VERSION* avp; APP* app; - ACTIVE_TASK* atp; vector::iterator app_iter; vector::iterator avp_iter; RESULT* rp; PERS_FILE_XFER* pxp; - for (i=0; iresult->project == project) { - atp->abort(); - active_tasks.remove(atp); - i--; - } - } + msg_printf(project, MSG_INFO, "Resetting project"); + active_tasks.abort_project(project); for (i=0; ipers_file_xfers.size(); i++) { pxp = pers_file_xfers->pers_file_xfers[i]; @@ -957,6 +952,8 @@ int CLIENT_STATE::reset_project(PROJECT* project) { } } + // if we're in the middle of a scheduler op to the project, abort it + // if (scheduler_op->state != SCHEDULER_OP_STATE_IDLE && scheduler_op->project == project ) { @@ -1009,6 +1006,8 @@ int CLIENT_STATE::detach_project(PROJECT* project) { reset_project(project); + msg_printf(project, MSG_INFO, "Detaching from project"); + // find project and remove it from the vector // for (iter = projects.begin(); iter != projects.end(); iter++) { diff --git a/client/client_state.h b/client/client_state.h index fa939bb9b6..eadcc6039b 100644 --- a/client/client_state.h +++ b/client/client_state.h @@ -103,6 +103,10 @@ public: int master_fetch_retry_cap, master_fetch_interval; int sched_retry_delay_min, sched_retry_delay_max; int pers_retry_delay_min, pers_retry_delay_max, pers_giveup; + bool activities_suspended; + bool previous_activities_suspended; + // if activities were suspended in the previous check_suspend(); + // this is needed to update GUI windows after suspension and close transfers/files. private: bool client_state_dirty; @@ -116,10 +120,6 @@ private: // if set, use hardwired numbers rather than running benchmarks bool run_cpu_benchmarks; // if set, run benchmarks on client startup - bool activities_suspended; - bool previous_activities_suspended; - // if activities were suspended in the previous check_suspend(); - // this is needed to update GUI windows after suspension and close transfers/files. int exit_after_app_start_secs; // if nonzero, exit this many seconds after starting an app time_t app_started; @@ -152,6 +152,7 @@ public: int report_result_error(RESULT &res, int err_num, const char *err_msg); // flag a result as having an error void set_client_state_dirty(char*); + int reset_project(PROJECT*); private: int link_app(PROJECT*, APP*); int link_file_info(PROJECT*, FILE_INFO*); @@ -162,12 +163,12 @@ private: void print_summary(); bool garbage_collect(); bool update_results(); - int reset_project(PROJECT*); // --------------- cs_account.C: +public: + int add_project(char* master_url, char* authenticator); private: int parse_account_files(); - int add_project(char* master_url, char* authenticator); // --------------- cs_apps.C: public: diff --git a/client/prefs.C b/client/prefs.C index 12a0aa4ed2..0d60bc1e7c 100644 --- a/client/prefs.C +++ b/client/prefs.C @@ -173,12 +173,12 @@ int GLOBAL_PREFS::parse(FILE* in, char* host_venue) { } if (strlen(host_venue)) { if (found_venue) { - msg_printf(NULL, MSG_INFO, "General preferences: using preferences for venue %s\n", host_venue); + msg_printf(NULL, MSG_INFO, "Using preferences for '%s'\n", host_venue); } else { - msg_printf(NULL, MSG_INFO, "General preferences: can't find special preferences for %s; using your default preferences\n", host_venue); + msg_printf(NULL, MSG_INFO, "No preferences for '%s'; using default preferences\n", host_venue); } } else { - msg_printf(NULL, MSG_INFO, "General preferences: no venue given; using your default general preferences\n"); + msg_printf(NULL, MSG_INFO, "Using default preferences\n"); } return 0; } diff --git a/client/scheduler_op.C b/client/scheduler_op.C index 97ff79e361..2945eccad3 100644 --- a/client/scheduler_op.C +++ b/client/scheduler_op.C @@ -345,14 +345,18 @@ bool SCHEDULER_OP::poll() { gstate.set_client_state_dirty("master URL fetch done"); http_ops->remove(&http_op); if (http_op.http_op_retval == 0) { - scope_messages.printf("SCHEDULER_OP::poll(): Got master file from %s; parsing\n", - project->master_url); + scope_messages.printf( + "SCHEDULER_OP::poll(): Got master file from %s; parsing\n", + project->master_url + ); retval = parse_master_file(urls); if (retval) { // master file parse failed. // if (project->tentative) { - project_add_failed(project); + PROJECT* project_temp = project; + project = 0; // keep detach(0) from removing HTTP OP + project_add_failed(project_temp); err = true; } else { project->master_fetch_failures++; @@ -380,7 +384,7 @@ bool SCHEDULER_OP::poll() { // If don't have any schedulers for this project, // it may be the wrong URL. notify the user // - if (project->scheduler_urls.size() == 0 && !err) { + if (!err && project->scheduler_urls.size() == 0) { if (project->tentative) { project_add_failed(project); } else { diff --git a/client/win/wingui.h b/client/win/wingui.h index 2e1ecc24a5..fdc4fef111 100755 --- a/client/win/wingui.h +++ b/client/win/wingui.h @@ -33,7 +33,6 @@ #include "filesys.h" #include "log_flags.h" #include "client_state.h" -#include "account.h" #include "error_numbers.h" #include "resource.h" #include "util.h"