- wrapper: add optional <exec_dir> element in <task> elements;

specifies a directory to run app in.
    macro-substitute project dir for $PROJECT_DIR.
    From Carl Christensen, more or less


svn path=/trunk/boinc/; revision=23075
This commit is contained in:
David Anderson 2011-02-20 04:01:04 +00:00
parent 151ca04258
commit 7ae1e2357d
2 changed files with 100 additions and 65 deletions

View File

@ -928,3 +928,12 @@ David 18 Feb 2011
cs_notice.cpp,h cs_notice.cpp,h
gui_rpc_server.h gui_rpc_server.h
gui_rpc_server_ops.cpp gui_rpc_server_ops.cpp
David 19 Feb 2011
- wrapper: add optional <exec_dir> element in <task> elements;
specifies a directory to run app in.
macro-substitute project dir for $PROJECT_DIR.
From Carl Christensen, more or less
samples/wrapper/
wrapper.cpp

View File

@ -61,6 +61,8 @@ using std::string;
struct TASK { struct TASK {
string application; string application;
string exec_dir;
// optional execution directory; macro-substituted for $PROJECT_DIR
string stdin_filename; string stdin_filename;
string stdout_filename; string stdout_filename;
string stderr_filename; string stderr_filename;
@ -93,7 +95,7 @@ struct TASK {
void kill(); void kill();
void stop(); void stop();
void resume(); void resume();
double cpu_time(); double cpu_time();
inline bool has_checkpointed() { inline bool has_checkpointed() {
bool changed = false; bool changed = false;
if (checkpoint_filename.size() == 0) return false; if (checkpoint_filename.size() == 0) return false;
@ -143,6 +145,22 @@ int TASK::parse(XML_PARSER& xp) {
return 0; return 0;
} }
else if (xp.parse_string(tag, "application", application)) continue; else if (xp.parse_string(tag, "application", application)) continue;
else if (xp.parse_str(tag, "exec_dir", buf, sizeof(buf))) {
while (1) {
char* p = strstr(buf, "$PROJECT_DIR");
if (!p) break;
strcpy(buf2, p+strlen("$PROJECT_DIR"));
if (strlen(aid.project_dir) > 0) {
strcpy(p, aid.project_dir);
} else {
strcpy(p, ".");
}
strcat(p, buf2);
}
exec_dir = buf;
//fprintf(stderr, "Found exec_dir = %s\n", exec_dir.c_str());
continue;
}
else if (xp.parse_string(tag, "stdin_filename", stdin_filename)) continue; else if (xp.parse_string(tag, "stdin_filename", stdin_filename)) continue;
else if (xp.parse_string(tag, "stdout_filename", stdout_filename)) continue; else if (xp.parse_string(tag, "stdout_filename", stdout_filename)) continue;
else if (xp.parse_string(tag, "stderr_filename", stderr_filename)) continue; else if (xp.parse_string(tag, "stderr_filename", stderr_filename)) continue;
@ -211,43 +229,43 @@ int parse_job_file() {
// We need to use CreateFile() to get them. Ugh. // We need to use CreateFile() to get them. Ugh.
// //
HANDLE win_fopen(const char* path, const char* mode) { HANDLE win_fopen(const char* path, const char* mode) {
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sa.nLength = sizeof(sa); sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE; sa.bInheritHandle = TRUE;
if (!strcmp(mode, "r")) { if (!strcmp(mode, "r")) {
return CreateFile( return CreateFile(
path, path,
GENERIC_READ, GENERIC_READ,
FILE_SHARE_READ, FILE_SHARE_READ,
&sa, &sa,
OPEN_EXISTING, OPEN_EXISTING,
0, 0 0, 0
); );
} else if (!strcmp(mode, "w")) { } else if (!strcmp(mode, "w")) {
return CreateFile( return CreateFile(
path, path,
GENERIC_WRITE, GENERIC_WRITE,
FILE_SHARE_WRITE, FILE_SHARE_WRITE,
&sa, &sa,
OPEN_ALWAYS, OPEN_ALWAYS,
0, 0 0, 0
); );
} else if (!strcmp(mode, "a")) { } else if (!strcmp(mode, "a")) {
HANDLE hAppend = CreateFile( HANDLE hAppend = CreateFile(
path, path,
GENERIC_WRITE, GENERIC_WRITE,
FILE_SHARE_WRITE, FILE_SHARE_WRITE,
&sa, &sa,
OPEN_ALWAYS, OPEN_ALWAYS,
0, 0 0, 0
); );
SetFilePointer(hAppend, 0, NULL, FILE_END); SetFilePointer(hAppend, 0, NULL, FILE_END);
return hAppend; return hAppend;
} else { } else {
return 0; return 0;
} }
} }
#endif #endif
@ -303,14 +321,14 @@ int TASK::run(int argct, char** argvt) {
// pass std handles to app // pass std handles to app
// //
startup_info.dwFlags = STARTF_USESTDHANDLES; startup_info.dwFlags = STARTF_USESTDHANDLES;
if (stdout_filename != "") { if (stdout_filename != "") {
boinc_resolve_filename_s(stdout_filename.c_str(), stdout_path); boinc_resolve_filename_s(stdout_filename.c_str(), stdout_path);
startup_info.hStdOutput = win_fopen(stdout_path.c_str(), "a"); startup_info.hStdOutput = win_fopen(stdout_path.c_str(), "a");
} }
if (stdin_filename != "") { if (stdin_filename != "") {
boinc_resolve_filename_s(stdin_filename.c_str(), stdin_path); boinc_resolve_filename_s(stdin_filename.c_str(), stdin_path);
startup_info.hStdInput = win_fopen(stdin_path.c_str(), "r"); startup_info.hStdInput = win_fopen(stdin_path.c_str(), "r");
} }
if (stderr_filename != "") { if (stderr_filename != "") {
boinc_resolve_filename_s(stderr_filename.c_str(), stderr_path); boinc_resolve_filename_s(stderr_filename.c_str(), stderr_path);
startup_info.hStdError = win_fopen(stderr_path.c_str(), "a"); startup_info.hStdError = win_fopen(stderr_path.c_str(), "a");
@ -323,10 +341,10 @@ int TASK::run(int argct, char** argvt) {
(LPSTR)command.c_str(), (LPSTR)command.c_str(),
NULL, NULL,
NULL, NULL,
TRUE, // bInheritHandles TRUE, // bInheritHandles
CREATE_NO_WINDOW|IDLE_PRIORITY_CLASS, CREATE_NO_WINDOW|IDLE_PRIORITY_CLASS,
NULL, NULL,
NULL, exec_dir.empty()?NULL:exec_dir.c_str(),
&startup_info, &startup_info,
&process_info &process_info
)) { )) {
@ -344,9 +362,9 @@ int TASK::run(int argct, char** argvt) {
char progname[256]; char progname[256];
char* argv[256]; char* argv[256];
char arglist[4096]; char arglist[4096];
FILE* stdout_file; FILE* stdout_file;
FILE* stdin_file; FILE* stdin_file;
FILE* stderr_file; FILE* stderr_file;
pid = fork(); pid = fork();
if (pid == -1) { if (pid == -1) {
@ -354,35 +372,43 @@ int TASK::run(int argct, char** argvt) {
return ERR_FORK; return ERR_FORK;
} }
if (pid == 0) { if (pid == 0) {
// we're in the child process here // we're in the child process here
// //
// open stdout, stdin if file names are given // open stdout, stdin if file names are given
// NOTE: if the application is restartable, // NOTE: if the application is restartable,
// we should deal with atomicity somehow // we should deal with atomicity somehow
// //
if (stdout_filename != "") { if (stdout_filename != "") {
boinc_resolve_filename_s(stdout_filename.c_str(), stdout_path); boinc_resolve_filename_s(stdout_filename.c_str(), stdout_path);
stdout_file = freopen(stdout_path.c_str(), "a", stdout); stdout_file = freopen(stdout_path.c_str(), "a", stdout);
if (!stdout_file) return ERR_FOPEN; if (!stdout_file) return ERR_FOPEN;
} }
if (stdin_filename != "") { if (stdin_filename != "") {
boinc_resolve_filename_s(stdin_filename.c_str(), stdin_path); boinc_resolve_filename_s(stdin_filename.c_str(), stdin_path);
stdin_file = freopen(stdin_path.c_str(), "r", stdin); stdin_file = freopen(stdin_path.c_str(), "r", stdin);
if (!stdin_file) return ERR_FOPEN; if (!stdin_file) return ERR_FOPEN;
} }
if (stderr_filename != "") { if (stderr_filename != "") {
boinc_resolve_filename_s(stderr_filename.c_str(), stderr_path); boinc_resolve_filename_s(stderr_filename.c_str(), stderr_path);
stderr_file = freopen(stderr_path.c_str(), "a", stderr); stderr_file = freopen(stderr_path.c_str(), "a", stderr);
if (!stderr_file) return ERR_FOPEN; if (!stderr_file) return ERR_FOPEN;
} }
// construct argv // construct argv
// TODO: use malloc instead of stack var // TODO: use malloc instead of stack var
// //
argv[0] = app_path; argv[0] = app_path;
strlcpy(arglist, command_line.c_str(), sizeof(arglist)); strlcpy(arglist, command_line.c_str(), sizeof(arglist));
argc = parse_command_line(arglist, argv+1); argc = parse_command_line(arglist, argv+1);
setpriority(PRIO_PROCESS, 0, PROCESS_IDLE_PRIORITY); setpriority(PRIO_PROCESS, 0, PROCESS_IDLE_PRIORITY);
if (!exec_dir.empty()) {
int retval = chdir(exec_dir.c_str());
#if 0
fprintf(stderr, "%s change to directory for task: %s\n",
retval ? "Failed to" : "Successful", exec_dir.c_str()
);
#endif
}
retval = execv(app_path, argv); retval = execv(app_path, argv);
perror("execv() failed: "); perror("execv() failed: ");
exit(ERR_EXEC); exit(ERR_EXEC);