mirror of https://github.com/BOINC/boinc.git
- wrapper: add "daemon" feature.
A task descriptor may contain <daemon>. Daemons are started before regular tasks, run concurrently with them, and are killed on exit. svn path=/trunk/boinc/; revision=23101
This commit is contained in:
parent
f30812355d
commit
d331ca86ed
|
@ -1125,3 +1125,12 @@ David 24 Feb 2011
|
||||||
|
|
||||||
html/user/
|
html/user/
|
||||||
friend.php
|
friend.php
|
||||||
|
|
||||||
|
David 24 Feb 2011
|
||||||
|
- wrapper: add "daemon" feature.
|
||||||
|
A task descriptor may contain <daemon>.
|
||||||
|
Daemons are started before regular tasks,
|
||||||
|
run concurrently with them, and are killed on exit.
|
||||||
|
|
||||||
|
samples/wrapper/
|
||||||
|
wrapper.cpp
|
||||||
|
|
|
@ -74,6 +74,9 @@ struct TASK {
|
||||||
string command_line;
|
string command_line;
|
||||||
double weight;
|
double weight;
|
||||||
// contribution of this task to overall fraction done
|
// contribution of this task to overall fraction done
|
||||||
|
bool is_daemon;
|
||||||
|
|
||||||
|
// dynamic stuff follows
|
||||||
double final_cpu_time;
|
double final_cpu_time;
|
||||||
double starting_cpu;
|
double starting_cpu;
|
||||||
// how much CPU time was used by tasks before this in the job file
|
// how much CPU time was used by tasks before this in the job file
|
||||||
|
@ -164,6 +167,7 @@ struct TASK {
|
||||||
};
|
};
|
||||||
|
|
||||||
vector<TASK> tasks;
|
vector<TASK> tasks;
|
||||||
|
vector<TASK> daemons;
|
||||||
APP_INIT_DATA aid;
|
APP_INIT_DATA aid;
|
||||||
bool graphics = false;
|
bool graphics = false;
|
||||||
|
|
||||||
|
@ -193,6 +197,7 @@ int TASK::parse(XML_PARSER& xp) {
|
||||||
weight = 1;
|
weight = 1;
|
||||||
final_cpu_time = 0;
|
final_cpu_time = 0;
|
||||||
stat_first = true;
|
stat_first = true;
|
||||||
|
pid = 0;
|
||||||
|
|
||||||
while (!xp.get(tag, sizeof(tag), is_tag)) {
|
while (!xp.get(tag, sizeof(tag), is_tag)) {
|
||||||
if (!is_tag) {
|
if (!is_tag) {
|
||||||
|
@ -226,6 +231,7 @@ int TASK::parse(XML_PARSER& xp) {
|
||||||
else if (xp.parse_string(tag, "checkpoint_filename", checkpoint_filename)) continue;
|
else if (xp.parse_string(tag, "checkpoint_filename", checkpoint_filename)) continue;
|
||||||
else if (xp.parse_string(tag, "fraction_done_filename", fraction_done_filename)) continue;
|
else if (xp.parse_string(tag, "fraction_done_filename", fraction_done_filename)) continue;
|
||||||
else if (xp.parse_double(tag, "weight", weight)) continue;
|
else if (xp.parse_double(tag, "weight", weight)) continue;
|
||||||
|
else if (xp.parse_bool(tag, "daemon", is_daemon)) continue;
|
||||||
}
|
}
|
||||||
return ERR_XML_PARSE;
|
return ERR_XML_PARSE;
|
||||||
}
|
}
|
||||||
|
@ -264,7 +270,11 @@ int parse_job_file() {
|
||||||
TASK task;
|
TASK task;
|
||||||
int retval = task.parse(xp);
|
int retval = task.parse(xp);
|
||||||
if (!retval) {
|
if (!retval) {
|
||||||
tasks.push_back(task);
|
if (task.is_daemon) {
|
||||||
|
daemons.push_back(task);
|
||||||
|
} else {
|
||||||
|
tasks.push_back(task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,6 +282,25 @@ int parse_job_file() {
|
||||||
return ERR_XML_PARSE;
|
return ERR_XML_PARSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int start_daemons(int argc, char** argv) {
|
||||||
|
for (unsigned int i=0; i<daemons.size(); i++) {
|
||||||
|
TASK& task = daemons[i];
|
||||||
|
int retval = task.run(argc, argv);
|
||||||
|
if (retval) return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kill_daemons() {
|
||||||
|
vector<int> daemon_pids;
|
||||||
|
for (unsigned int i=0; i<daemons.size(); i++) {
|
||||||
|
TASK& task = daemons[i];
|
||||||
|
if (task.pid) {
|
||||||
|
daemon_pids.push_back(task.pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kill_all(daemon_pids);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// CreateProcess() takes HANDLEs for the stdin/stdout.
|
// CreateProcess() takes HANDLEs for the stdin/stdout.
|
||||||
// We need to use CreateFile() to get them. Ugh.
|
// We need to use CreateFile() to get them. Ugh.
|
||||||
|
@ -478,7 +507,6 @@ int TASK::run(int argct, char** argvt) {
|
||||||
} else {
|
} else {
|
||||||
retval = execv(app_path, argv);
|
retval = execv(app_path, argv);
|
||||||
}
|
}
|
||||||
if (env_vars) delete [] env_vars; // never really gets here after the execve
|
|
||||||
perror("execv() failed: ");
|
perror("execv() failed: ");
|
||||||
exit(ERR_EXEC);
|
exit(ERR_EXEC);
|
||||||
} // pid = 0 i.e. child proc of the fork
|
} // pid = 0 i.e. child proc of the fork
|
||||||
|
@ -512,7 +540,10 @@ bool TASK::poll(int& status) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// kill this task (gracefully if possible) and any other subprocesses
|
||||||
|
//
|
||||||
void TASK::kill() {
|
void TASK::kill() {
|
||||||
|
kill_daemons();
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// on Win, just kill all our descendants
|
// on Win, just kill all our descendants
|
||||||
//
|
//
|
||||||
|
@ -556,6 +587,21 @@ void TASK::resume() {
|
||||||
suspended = false;
|
suspended = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double TASK::cpu_time() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
double x;
|
||||||
|
int retval = boinc_process_cpu_time(pid_handle, x);
|
||||||
|
if (retval) return wall_cpu_time;
|
||||||
|
return x;
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
// There's no easy way to get another process's CPU time in Mac OS X
|
||||||
|
//
|
||||||
|
return wall_cpu_time;
|
||||||
|
#else
|
||||||
|
return linux_cpu_time(pid);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void poll_boinc_messages(TASK& task) {
|
void poll_boinc_messages(TASK& task) {
|
||||||
BOINC_STATUS status;
|
BOINC_STATUS status;
|
||||||
boinc_get_status(&status);
|
boinc_get_status(&status);
|
||||||
|
@ -582,21 +628,6 @@ void poll_boinc_messages(TASK& task) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double TASK::cpu_time() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
double x;
|
|
||||||
int retval = boinc_process_cpu_time(pid_handle, x);
|
|
||||||
if (retval) return wall_cpu_time;
|
|
||||||
return x;
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
// There's no easy way to get another process's CPU time in Mac OS X
|
|
||||||
//
|
|
||||||
return wall_cpu_time;
|
|
||||||
#else
|
|
||||||
return linux_cpu_time(pid);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void send_status_message(
|
void send_status_message(
|
||||||
TASK& task, double frac_done, double checkpoint_cpu_time
|
TASK& task, double frac_done, double checkpoint_cpu_time
|
||||||
) {
|
) {
|
||||||
|
@ -679,6 +710,13 @@ int main(int argc, char** argv) {
|
||||||
total_weight += tasks[i].weight;
|
total_weight += tasks[i].weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retval = start_daemons(argc, argv);
|
||||||
|
if (retval) {
|
||||||
|
fprintf(stderr, "start_daemons(): %d\n", retval);
|
||||||
|
kill_daemons();
|
||||||
|
boinc_finish(retval);
|
||||||
|
}
|
||||||
|
|
||||||
// loop over tasks
|
// loop over tasks
|
||||||
//
|
//
|
||||||
for (i=0; i<tasks.size(); i++) {
|
for (i=0; i<tasks.size(); i++) {
|
||||||
|
@ -705,6 +743,7 @@ int main(int argc, char** argv) {
|
||||||
// as recoverable, and restart us.
|
// as recoverable, and restart us.
|
||||||
// We don't want this, so return an 8-bit error code.
|
// We don't want this, so return an 8-bit error code.
|
||||||
//
|
//
|
||||||
|
kill_daemons();
|
||||||
boinc_finish(EXIT_CHILD_FAILED);
|
boinc_finish(EXIT_CHILD_FAILED);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -723,6 +762,7 @@ int main(int argc, char** argv) {
|
||||||
write_checkpoint(i+1, checkpoint_cpu_time);
|
write_checkpoint(i+1, checkpoint_cpu_time);
|
||||||
weight_completed += task.weight;
|
weight_completed += task.weight;
|
||||||
}
|
}
|
||||||
|
kill_daemons();
|
||||||
boinc_finish(0);
|
boinc_finish(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue