Condor interface: various fixes, mostly from Jaime Frey

- XML parser: for parse_string(), malloc the 256KB buffer instead of
    allocating it on the stack; the latter crashes threads with 32KB stacks.
    However, do the malloc() only if we've actually seen the start tag
    (this required a bit of code shuffle).
- BOINC GAHP: escape spaces in error msgs
This commit is contained in:
David Anderson 2013-05-27 11:45:10 -07:00
parent f30097d175
commit 8009a8cecb
5 changed files with 100 additions and 81 deletions

View File

@ -540,18 +540,9 @@ int XML_PARSER::scan_cdata(char* buf, int len) {
}
}
#define MAX_XML_STRING 262144
// We just parsed "parsed_tag".
// If it matches "start_tag", and is followed by a string
// and by the matching close tag, return the string in "buf",
// and return true.
//
bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
bool eof;
char end_tag[TAG_BUF_LEN], tag[TAG_BUF_LEN];
static inline bool is_empty_string(char* parsed_tag, const char* start_tag) {
size_t n = strlen(parsed_tag);
char tag[TAG_BUF_LEN];
// handle the archaic form <tag/>, which means empty string
//
@ -559,14 +550,17 @@ bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
strcpy(tag, parsed_tag);
tag[n-1] = 0;
if (!strcmp(tag, start_tag)) {
strcpy(buf, "");
return true;
}
}
return false;
}
// check for start tag
//
if (strcmp(parsed_tag, start_tag)) return false;
// we've parsed the start tag of a string; parse the string itself.
//
bool XML_PARSER::parse_str_aux(const char* start_tag, char* buf, int len) {
bool eof;
char end_tag[TAG_BUF_LEN], tag[TAG_BUF_LEN];
end_tag[0] = '/';
strcpy(end_tag+1, start_tag);
@ -598,12 +592,37 @@ bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
return true;
}
// We just parsed "parsed_tag".
// If it matches "start_tag", and is followed by a string
// and by the matching close tag, return the string in "buf",
// and return true.
//
bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
if (is_empty_string(parsed_tag, start_tag)) {
strcpy(buf, "");
return true;
}
if (strcmp(parsed_tag, start_tag)) return false;
return parse_str_aux(start_tag, buf, len);
}
#define MAX_XML_STRING 262144
// same, for std::string
//
bool XML_PARSER::parse_string(const char* start_tag, string& str) {
char buf[MAX_XML_STRING];
bool flag = parse_str(start_tag, buf, sizeof(buf));
if (!flag) return false;
str = buf;
return true;
if (is_empty_string(parsed_tag, start_tag)) {
str = "";
return true;
}
if (strcmp(parsed_tag, start_tag)) return false;
char *buf=(char *)malloc(MAX_XML_STRING);
bool flag = parse_str_aux(start_tag, buf, MAX_XML_STRING);
if (flag) {
str = buf;
}
free(buf);
return flag;
}
// Same, for integers

View File

@ -244,7 +244,10 @@ struct XML_PARSER {
strip_whitespace(buf);
return retval;
}
bool parse_str_aux(const char*, char*, int);
// interface starts here
//
bool parse_start(const char*);
bool parse_str(const char*, char*, int);
bool parse_string(const char*, std::string&);
@ -332,34 +335,6 @@ inline bool parse_double(const char* buf, const char* tag, double& x) {
return true;
}
#if 0
// Same, for unsigned long
//
inline bool parse_ulong(const char* buf, const char* tag, unsigned long& x) {
const char* p = strstr(buf, tag);
if (!p) return false;
errno = 0;
unsigned long y = strtoul(p+strlen(tag), NULL, 0);
if (errno) return false;
x = y;
return true;
}
// Same, for unsigned long long
//
inline bool parse_ulonglong(
const char* buf, const char* tag, unsigned long long& x
) {
const char* p = strstr(buf, tag);
if (!p) return false;
errno = 0;
unsigned long long y = boinc_strtoull(p+strlen(tag), NULL, 0);
if (errno) return false;
x = y;
return true;
}
#endif
extern bool parse(char* , char* );
extern bool parse_str(const char*, const char*, char*, int);
extern bool parse_str(const char* buf, const char* tag, std::string& dest);

View File

@ -1,6 +1,9 @@
// test program for XML parser
#include <stdio.h>
#include <string>
using std::string;
#include "parse.h"
@ -12,6 +15,7 @@ void parse(FILE* f) {
char foo[64];
int val;
double x;
string s;
strcpy(name, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
mf.init_file(f);
@ -29,8 +33,9 @@ void parse(FILE* f) {
if (xp.match_tag("/blah")) {
printf("success\n");
return;
} else if (xp.parse_str("str", name, 33)) {
printf("got str: [%s]\n", name);
} else if (xp.parse_str("str", name, 64)) {
//} else if (xp.parse_string("str", s)) {
printf("got str: [%s]\n", s.c_str());
} else if (xp.parse_int("int", val)) {
printf("got int: %d\n", val);
} else if (xp.parse_double("double", x)) {

View File

@ -317,7 +317,7 @@ int submit_jobs(
error_msg = "";
int temp;
while (fgets(buf, 256, reply)) {
printf("submit_batch reply: %s", buf);
//printf("submit_batch reply: %s", buf);
if (parse_int(buf, "<batch_id>", temp)) {
retval = 0;
continue;
@ -527,7 +527,7 @@ int get_output_file(
sprintf(url, "%sget_output.php?cmd=workunit_file&auth_str=%s&wu_name=%s&file_num=%d",
project_url, authenticator, job_name, file_num
);
printf("fetching %s to %s\n", url, dst_path);
//printf("fetching %s to %s\n", url, dst_path);
int retval = do_http_get(url, dst_path);
error_msg = "";
if (retval) {

View File

@ -87,6 +87,24 @@ int compute_md5(string path, LOCAL_FILE& f) {
return md5_file(path.c_str(), f.md5, f.nbytes);
}
const char *escape_str(const string &str)
{
static string out;
out = "";
for ( const char *ptr = str.c_str(); *ptr; ptr++ ) {
switch ( *ptr ) {
case ' ':
case '\\':
case '\r':
case '\n':
out += '\\';
default:
out += *ptr;
}
}
return out.c_str();
}
// Get a list of the input files used by the batch.
// Get their MD5s.
// See if they're already on the server.
@ -206,8 +224,8 @@ void handle_submit(COMMAND& c) {
project_url, authenticator, req.app_name, NULL, td, error_msg
);
if (retval) {
sprintf(buf, "error getting templates: %d\n", retval);
s = string(buf) + error_msg;
sprintf(buf, "error\\ getting\\ templates:\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
c.out = strdup(s.c_str());
return;
}
@ -215,22 +233,22 @@ void handle_submit(COMMAND& c) {
project_url, authenticator, req.batch_name, req.app_name, req.batch_id, error_msg
);
if (retval) {
sprintf(buf, "error creating batch: %d ", retval);
s = string(buf) + error_msg;
sprintf(buf, "error\\ creating\\ batch:\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
c.out = strdup(s.c_str());
return;
}
retval = process_input_files(req, error_msg);
if (retval) {
sprintf(buf, "error processing input files: %d ", retval);
s = string(buf) + error_msg;
sprintf(buf, "error\\ processing\\ input\\ files:\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
c.out = strdup(s.c_str());
return;
}
retval = submit_jobs(project_url, authenticator, req, error_msg);
if (retval) {
sprintf(buf, "error submitting jobs: %d ", retval);
s = string(buf) + error_msg;
sprintf(buf, "error\\ submitting\\ jobs:\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
} else {
s = "NULL";
}
@ -254,13 +272,15 @@ void handle_query_batches(COMMAND&c) {
project_url, authenticator, c.batch_names, reply, error_msg
);
if (retval) {
sprintf(buf, "error querying batch: %d ", retval);
s = string(buf) + error_msg;
sprintf(buf, "error\\ querying\\ batch:\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
} else {
s = string("NULL ");
sprintf(buf, "%d", (int)reply.jobs.size());
s += string(buf);
for (unsigned int i=0; i<reply.jobs.size(); i++) {
QUERY_BATCH_JOB &j = reply.jobs[i];
sprintf(buf, "%s %s ", j.job_name.c_str(), j.status.c_str());
sprintf(buf, " %s %s", j.job_name.c_str(), j.status.c_str());
s += string(buf);
}
}
@ -339,8 +359,8 @@ void handle_fetch_output(COMMAND& c) {
project_url, authenticator, NULL, req.job_name, td, error_msg
);
if (retval) {
sprintf(buf, "error getting templates: %d\n", retval);
s = string(buf) + error_msg;
sprintf(buf, "error\\ getting\\ templates:\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
c.out = strdup(s.c_str());
return;
}
@ -351,8 +371,8 @@ void handle_fetch_output(COMMAND& c) {
project_url, authenticator, req.job_name, cjd, error_msg
);
if (retval) {
sprintf(buf, "query_completed_job() returned %d ", retval);
s = string(buf) + error_msg;
sprintf(buf, "query_completed_job()\\ returned\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
goto done;
}
sprintf(buf, " %d %f %f", cjd.exit_status, cjd.elapsed_time, cjd.cpu_time);
@ -364,7 +384,7 @@ void handle_fetch_output(COMMAND& c) {
sprintf(path, "%s/%s", req.dir, req.stderr_filename.c_str());
FILE* f = fopen(path, "w");
if (!f) {
sprintf(buf, "can't open stderr output file %s ", path);
sprintf(buf, "can't\\ open\\ stderr\\ output\\ file\\ %s ", path);
s = string(buf);
goto done;
}
@ -380,13 +400,13 @@ void handle_fetch_output(COMMAND& c) {
project_url, authenticator, req.job_name, 0, path, error_msg
);
if (retval) {
sprintf(buf, "get_output_file() returned %d ", retval);
s = string(buf) + error_msg;
sprintf(buf, "get_output_file()\\ returned\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
} else {
sprintf(buf, "cd %s; unzip temp.zip");
retval = system(buf);
if (retval) {
s = string("unzip failed");
s = string("unzip\\ failed");
}
}
} else if (req.fetch_all) {
@ -396,8 +416,8 @@ void handle_fetch_output(COMMAND& c) {
project_url, authenticator, req.job_name, i, path, error_msg
);
if (retval) {
sprintf(buf, "get_output_file() returned %d ", retval);
s = string(buf) + error_msg;
sprintf(buf, "get_output_file()\\ returned\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
break;
}
}
@ -406,7 +426,7 @@ void handle_fetch_output(COMMAND& c) {
char* lname = req.file_descs[i].src;
int j = output_file_index(td, lname);
if (j < 0) {
sprintf(buf, "requested file %s not in template", lname);
sprintf(buf, "requested\\ file\\ %s\\ not\\ in\\ template", lname);
s = string(buf);
goto done;
}
@ -415,8 +435,8 @@ void handle_fetch_output(COMMAND& c) {
project_url, authenticator, req.job_name, i, path, error_msg
);
if (retval) {
sprintf(buf, "get_output_file() returned %d ", retval);
s = string(buf) + error_msg;
sprintf(buf, "get_output_file()\\ returned\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
break;
}
}
@ -438,7 +458,7 @@ void handle_fetch_output(COMMAND& c) {
sprintf(buf, "mv %s/%s %s", req.dir, of.src, dst_path);
retval = system(buf);
if (retval) {
s = string("mv failed");
s = string("mv\\ failed");
}
}
done:
@ -464,8 +484,8 @@ void handle_abort_jobs(COMMAND& c) {
string s;
char buf[256];
if (retval) {
sprintf(buf, "abort_jobs() returned %d \n", retval);
s = string(buf) + error_msg;
sprintf(buf, "abort_jobs()\\ returned\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
} else {
s = "NULL";
}
@ -477,8 +497,8 @@ void handle_ping(COMMAND& c) {
char buf[256];
int retval = ping_server(project_url, error_msg);
if (retval) {
sprintf(buf, "ping_server returned %d \n", retval);
s = string(buf) + error_msg;
sprintf(buf, "ping_server\\ returned\\ %d\\ ", retval);
s = string(buf) + escape_str(error_msg);
} else {
s = "NULL";
}