diff --git a/api/boinc_api.C b/api/boinc_api.C index 12a33aefc2..95fca27b61 100644 --- a/api/boinc_api.C +++ b/api/boinc_api.C @@ -90,21 +90,27 @@ static volatile bool have_new_trickle_up = false; static volatile bool have_trickle_down = true; // on first call, scan slot dir for msgs static volatile int heartbeat_giveup_time; + // interrupt count value at which to give up on core client static volatile bool heartbeat_active; // if false, suppress heartbeat mechanism #ifdef _WIN32 static volatile int nrunning_ticks = 0; #endif +static volatile int interrupt_count = 0; + // number of timer interrupts + // used to measure elapsed time in a way that's + // not affected by user changing system clock, + // and that doesn't have big jumps around hibernation static double fpops_per_cpu_sec = 0; static double fpops_cumulative = 0; #define TIMER_PERIOD 1 - // period of worker-thread timer + // period of worker-thread timer interrupts. // This determines the resolution of fraction done and CPU time reporting // to the core client, and of checkpoint enabling. // It doesn't influence graphics, so 1 sec is enough. -#define HEARTBEAT_GIVEUP_PERIOD 30 - // quit if no heartbeat from core in this #secs +#define HEARTBEAT_GIVEUP_PERIOD (30/TIMER_PERIOD) + // quit if no heartbeat from core in this #interrupts #define HEARTBEAT_TIMEOUT_PERIOD 35 // quit if we cannot aquire slot resource in this #secs @@ -275,7 +281,7 @@ int boinc_init_options_general(BOINC_OPTIONS& opt) { last_wu_cpu_time = aid.wu_cpu_time; heartbeat_active = !standalone; - heartbeat_giveup_time = time(0) + HEARTBEAT_GIVEUP_PERIOD; + heartbeat_giveup_time = interrupt_count + HEARTBEAT_GIVEUP_PERIOD; return 0; } @@ -450,7 +456,7 @@ static void handle_heartbeat_msg() { char buf[MSG_CHANNEL_SIZE]; if (app_client_shm->shm->heartbeat.get_msg(buf)) { if (match_tag(buf, "")) { - heartbeat_giveup_time = time(0) + HEARTBEAT_GIVEUP_PERIOD; + heartbeat_giveup_time = interrupt_count + HEARTBEAT_GIVEUP_PERIOD; } if (match_tag(buf, "")) { heartbeat_active = true; @@ -533,7 +539,7 @@ static void handle_process_control_msg() { } boinc_sleep(1.0); } - heartbeat_giveup_time = time(0) + HEARTBEAT_GIVEUP_PERIOD; + heartbeat_giveup_time = interrupt_time + HEARTBEAT_GIVEUP_PERIOD; #endif } } @@ -566,6 +572,7 @@ static void CALLBACK worker_timer( #else static void worker_timer(int /*a*/) { #endif + interrupt_count++; if (!ready_to_checkpoint) { time_until_checkpoint -= TIMER_PERIOD; if (time_until_checkpoint <= 0) { @@ -591,11 +598,10 @@ static void worker_timer(int /*a*/) { // (unless we're checkpointing) // if (!checkpointing && options.check_heartbeat && heartbeat_active) { - int now = time(0); - if (heartbeat_giveup_time < now) { + if (heartbeat_giveup_time < interrupt_count) { fprintf(stderr, "No heartbeat from core client for %d sec - exiting\n", - now - (heartbeat_giveup_time - HEARTBEAT_GIVEUP_PERIOD) + interrupt_count - (heartbeat_giveup_time - HEARTBEAT_GIVEUP_PERIOD) ); if (options.direct_process_action) { boinc_exit(0); diff --git a/checkin_notes b/checkin_notes index 52df1596ca..b1058e346b 100755 --- a/checkin_notes +++ b/checkin_notes @@ -9477,3 +9477,28 @@ David 23 July 2005 md5_file.C,h miofile.C network.C + +David 23 July 2005 + - API: change heartbeat mechanism so that instead of using time(0), + it uses its own counter (incremented on interrupt). + This avoid specious heartbeat timeout + when user resets system clock. + It should also fix problem where BOINC restarts + after hibernation, app runs before core client, + and it gets heartbeat timeout. + - Core client: add "-no_gui_rpc" cmdline option. + If present, don't create listening socket for GUI RPC. + (Useful if bind() doesn't work). + - shared memory: in shmget() mode, first try 0666; + if that fails, try SHM_R|SHM_W + This is just paranoia, in case 21/July checkin + breaks some platform. + + api/ + boinc_api.C + client/ + client_state.C,h + cs_cmdline.C + gui_rpc_server.C,h + lib/ + shmem.C diff --git a/client/client_state.C b/client/client_state.C index eb7502c531..45de262a21 100644 --- a/client/client_state.C +++ b/client/client_state.C @@ -118,6 +118,7 @@ CLIENT_STATE::CLIENT_STATE() { total_wall_cpu_time_this_period = 0; must_schedule_cpus = true; want_network_flag = false; + no_gui_rpc = false; } #if 0 @@ -357,8 +358,10 @@ int CLIENT_STATE::init() { // set_client_state_dirty("init"); - retval = gui_rpcs.init(); - if (retval) return retval; + if (!no_gui_rpc) { + retval = gui_rpcs.init(); + if (retval) return retval; + } acct_mgr_info.init(); diff --git a/client/client_state.h b/client/client_state.h index c4022c1604..8a9d913a42 100644 --- a/client/client_state.h +++ b/client/client_state.h @@ -191,6 +191,7 @@ public: bool want_network_flag; bool want_network(); void network_available(); + bool no_gui_rpc; private: int link_app(PROJECT*, APP*); int link_file_info(PROJECT*, FILE_INFO*); diff --git a/client/cs_cmdline.C b/client/cs_cmdline.C index 108a593feb..7c32cd37db 100644 --- a/client/cs_cmdline.C +++ b/client/cs_cmdline.C @@ -47,7 +47,9 @@ static void print_options(char* prog) { " -check_all_logins for idle detection, check remote logins\n too" " -allow_remote_gui_rpc allow remote GUI RPC connections\n" " -redirectio redirect stdout and stderr to log files\n" - " -dir use given dir as BOINC home\n", + " -dir use given dir as BOINC home\n" + " -no_gui_rpc don't allow GUI RPC, don't make socket\n" + , prog ); } @@ -167,6 +169,8 @@ void CLIENT_STATE::parse_cmdline(int argc, char** argv) { if (chdir(argv[++i])) { perror("chdir"); } + } else if (ARG(no_gui_rpc)) { + no_gui_rpc = true; } else { printf("Unknown option: %s\n", argv[i]); show_options = true; diff --git a/client/gui_rpc_server.C b/client/gui_rpc_server.C index 5e20b10f7a..1616c92e04 100644 --- a/client/gui_rpc_server.C +++ b/client/gui_rpc_server.C @@ -656,6 +656,10 @@ int GUI_RPC_CONN::handle_rpc() { return 0; } +GUI_RPC_CONN_SET::GUI_RPC_CONN_SET() { + lsock = -1; +} + int GUI_RPC_CONN_SET::get_password() { strcpy(password, ""); if (boinc_file_exists(GUI_RPC_PASSWD_FILE)) { diff --git a/client/gui_rpc_server.h b/client/gui_rpc_server.h index e05c8cfc83..f178b92ff0 100644 --- a/client/gui_rpc_server.h +++ b/client/gui_rpc_server.h @@ -45,6 +45,7 @@ class GUI_RPC_CONN_SET { int get_password(); int insert(GUI_RPC_CONN*); public: + GUI_RPC_CONN_SET(); char password[256]; bool poll(); int init(); diff --git a/lib/shmem.C b/lib/shmem.C index e94c50e547..2de79633c8 100755 --- a/lib/shmem.C +++ b/lib/shmem.C @@ -50,7 +50,6 @@ #ifdef _WIN32 HANDLE create_shmem(LPCTSTR seg_name, int size, void** pp, bool disable_mapview) { - SECURITY_ATTRIBUTES security; HANDLE hMap; DWORD dwError = 0; @@ -95,8 +94,10 @@ int detach_shmem(HANDLE hMap, void* p) { int create_shmem(key_t key, int size, void** pp) { int id; - assert(pp!=NULL); - id = shmget(key, size, IPC_CREAT|SHM_R|SHM_W); + id = shmget(key, size, IPC_CREAT|0666); + if (id < 0) { + id = shmget(key, size, IPC_CREAT|SHM_R|SHM_W); + } if (id < 0) { return ERR_SHMGET; } @@ -122,7 +123,7 @@ int destroy_shmem(key_t key){ int attach_shmem(key_t key, void** pp){ void* p; int id; - assert(pp!=NULL); + id = shmget(key, 0, 0); if (id < 0) { return ERR_SHMGET; @@ -137,7 +138,6 @@ int attach_shmem(key_t key, void** pp){ int detach_shmem(void* p) { int retval; - assert(p!=NULL); retval = shmdt((char *)p); return retval; }