aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-04-22 18:32:46 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-04-22 18:32:46 +0200
commit16143f324c030579d447679d5741b63796a4ac9b (patch)
tree887fa63758205ab24fae5395ac2e4244a2e51067
parent1fef20e94bd9960da1b2ea0b2a41b94a79f8abc5 (diff)
Make HTTP soft error handling more robust
-rw-r--r--bbot/agent.cxx38
-rw-r--r--bbot/utility4
-rw-r--r--bbot/utility.txx31
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 ();
}
}