diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2017-04-22 18:32:46 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2017-04-22 18:32:46 +0200 |
commit | 16143f324c030579d447679d5741b63796a4ac9b (patch) | |
tree | 887fa63758205ab24fae5395ac2e4244a2e51067 | |
parent | 1fef20e94bd9960da1b2ea0b2a41b94a79f8abc5 (diff) |
Make HTTP soft error handling more robust
-rw-r--r-- | bbot/agent.cxx | 38 | ||||
-rw-r--r-- | bbot/utility | 4 | ||||
-rw-r--r-- | bbot/utility.txx | 31 |
3 files changed, 57 insertions, 16 deletions
diff --git a/bbot/agent.cxx b/bbot/agent.cxx index 683bd73..0840739 100644 --- a/bbot/agent.cxx +++ b/bbot/agent.cxx @@ -873,14 +873,30 @@ try "--header", "Content-Type: text/manifest", "--max-time", ops.request_timeout ()); - serialize_manifest (tq, c.out, u, "task request"); + // This is tricky/hairy: we may fail hard parsing the output before + // seeing that curl exited with an error and failing softly. + // + bool f (false); + + try + { + serialize_manifest (tq, c.out, u, "task request", false); + } + catch (const failed&) {f = true;} + c.out.close (); - tr = parse_manifest<task_response_manifest> ( - c.in, u, "task response"); + if (!f) + try + { + tr = parse_manifest<task_response_manifest> ( + c.in, u, "task response", false); + } + catch (const failed&) {f = true;} + c.in.close (); - if (!c.wait ()) + if (!c.wait () || f) throw_generic_error (EIO); } catch (const system_error& e) @@ -971,10 +987,20 @@ try "--header", "Content-Type: text/manifest", "--max-time", ops.request_timeout ()); - serialize_manifest (rq, c.out, u, "task request"); + // This is tricky/hairy: we may fail hard writing the input before + // seeing that curl exited with an error and failing softly. + // + bool f (false); + + try + { + serialize_manifest (rq, c.out, u, "task request"); + } + catch (const failed&) {f = true;} + c.out.close (); - if (!c.wait ()) + if (!c.wait () || f) throw_generic_error (EIO); } catch (const system_error& e) diff --git a/bbot/utility b/bbot/utility index 7fe6bfb..3424f2b 100644 --- a/bbot/utility +++ b/bbot/utility @@ -143,6 +143,7 @@ namespace bbot parse_manifest (istream&, const string& name, const char* what, + bool fail_hard = true, bool ignore_unknown = true); template <typename T> @@ -154,7 +155,8 @@ namespace bbot serialize_manifest (const T&, ostream&, const string& name, - const char* what); + const char* what, + bool fail_hard = true); } #include <bbot/utility.txx> diff --git a/bbot/utility.txx b/bbot/utility.txx index 4ee4c6f..231bd8f 100644 --- a/bbot/utility.txx +++ b/bbot/utility.txx @@ -157,7 +157,7 @@ namespace bbot fail << what << " manifest file " << f << " does not exist"; ifdstream ifs (f); - return parse_manifest<T> (ifs, f.string (), what, ignore_unknown); + return parse_manifest<T> (ifs, f.string (), what, true, ignore_unknown); } catch (const system_error& e) // EACCES, etc. { @@ -171,6 +171,7 @@ namespace bbot parse_manifest (istream& is, const string& name, const char* what, + bool hard, bool ignore_unknown) { using namespace butl; @@ -182,15 +183,19 @@ namespace bbot } catch (const manifest_parsing& e) { - fail << "invalid " << what << " manifest: " - << name << ':' << e.line << ':' << e.column << ": " << e.description - << endf; + diag_record dr; if (hard) dr << fail; else dr << error; + + dr << "invalid " << what << " manifest: " + << name << ':' << e.line << ':' << e.column << ": " << e.description; } catch (const io_error& e) { - fail << "unable to read " << what << " manifest " << name << ": " << e - << endf; + diag_record dr; if (hard) dr << fail; else dr << error; + + dr << "unable to read " << what << " manifest " << name << ": " << e; } + + throw failed (); } template <typename T> @@ -205,7 +210,7 @@ namespace bbot ofdstream ofs (f, ios::binary); auto_rmfile arm (f); // Try to remove on failure ignoring errors. - serialize_manifest (m, ofs, f.string (), what); + serialize_manifest (m, ofs, f.string (), what, true); ofs.close (); arm.cancel (); @@ -221,7 +226,8 @@ namespace bbot serialize_manifest (const T& m, ostream& os, const string& name, - const char* what) + const char* what, + bool hard) { using namespace butl; @@ -229,14 +235,21 @@ namespace bbot { manifest_serializer s (os, name); m.serialize (s); + return; } catch (const manifest_serialization& e) { - fail << "invalid " << what << " manifest: " << e.description; + diag_record dr; if (hard) dr << fail; else dr << error; + + dr << "invalid " << what << " manifest: " << e.description; } catch (const io_error& e) { + diag_record dr; if (hard) dr << fail; else dr << error; + fail << "unable to write " << what << " manifest " << name << ": " << e; } + + throw failed (); } } |