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;
}