aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-08-06 21:10:06 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-08-06 21:10:06 +0200
commit0238e9ef50f115d98cf860a476bff8b5edff12ff (patch)
treed776a6eb614f2956b38bf6536e532f4241d66bae
parentd2ef3a8d0ee8005b200fa238ab3cfc8eb09f783a (diff)
Handle the case where machine is shutdown/rebooted from within
-rw-r--r--bbot/agent/machine.cxx149
1 files changed, 77 insertions, 72 deletions
diff --git a/bbot/agent/machine.cxx b/bbot/agent/machine.cxx
index c2ded27..9502021 100644
--- a/bbot/agent/machine.cxx
+++ b/bbot/agent/machine.cxx
@@ -180,8 +180,10 @@ namespace bbot
print_info (diag_record&) override;
private:
+ // Throw system_error in case of communication errors.
+ //
void
- monitor_command (const string&, bool fail_hard = true);
+ monitor_command (const string&);
private:
path kvm; // Hypervisor binary.
@@ -333,44 +335,55 @@ namespace bbot
bool kvm_machine::
shutdown (size_t& seconds)
{
- monitor_command ("system_powerdown");
-
// Wait for up to the specified number if seconds for the machine to
- // shutdown.
- //
- // Since things sometimes get stuck for no apparent reason, keep repeating
- // the the request every minute.
+ // shutdown. And handle the case where it was shutdown from within.
//
- for (size_t s;; )
+ try
{
- s = 60;
- bool r (seconds < s ? wait (seconds) : wait (s));
- seconds -= (60 - s);
-
- if (r || seconds == 0)
- return r;
+ monitor_command ("system_powerdown");
+ }
+ catch (const system_error& e)
+ {
+ size_t t (0);
+ if (wait (t))
+ return true;
- try
- {
- monitor_command ("system_powerdown", false);
- }
- catch (const failed&) {}
+ fail << "unable to communicate with qemu monitor: " << e;
}
- return false;
+ return wait (seconds);
}
void kvm_machine::
forcedown (bool fh)
{
- monitor_command ("system_reset", fh);
+ try
+ {
+ monitor_command ("system_reset");
+ }
+ catch (const system_error& e)
+ {
+ size_t t (0);
+ if (wait (t, fh))
+ return;
+
+ fail (fh) << "unable to communicate with qemu monitor: " << e;
+ }
+
wait (fh);
}
void kvm_machine::
suspend ()
{
- monitor_command ("stop");
+ try
+ {
+ monitor_command ("stop");
+ }
+ catch (const system_error& e)
+ {
+ fail << "unable to communicate with qemu monitor: " << e;
+ }
}
void kvm_machine::
@@ -408,70 +421,62 @@ namespace bbot
}
void kvm_machine::
- monitor_command (const string& c, bool fh)
+ monitor_command (const string& c)
{
- try
- {
- sockaddr_un addr;
- addr.sun_family = AF_LOCAL;
- strcpy (addr.sun_path, monitor.string ().c_str ()); // Size check in ctor
+ sockaddr_un addr;
+ addr.sun_family = AF_LOCAL;
+ strcpy (addr.sun_path, monitor.string ().c_str ()); // Size check in ctor
- auto_fd sock (socket (AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0));
+ auto_fd sock (socket (AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0));
- if (sock.get () == -1)
- throw_system_error (errno);
+ if (sock.get () == -1)
+ throw_system_error (errno);
- if (connect (sock.get (),
- reinterpret_cast<sockaddr*> (&addr),
- sizeof (addr)) == -1)
- throw_system_error (errno);
+ if (connect (sock.get (),
+ reinterpret_cast<sockaddr*> (&addr),
+ sizeof (addr)) == -1)
+ throw_system_error (errno);
- // Read until we get something.
- //
- auto readsome = [&sock] ()
+ // Read until we get something.
+ //
+ auto readsome = [&sock] ()
+ {
+ ifdstream ifs (move (sock),
+ fdstream_mode::non_blocking,
+ ostream::badbit);
+
+ char buf[256];
+ for (streamsize n (0), m (0);
+ n == 0 || m != 0;
+ m = ifs.readsome (buf, sizeof (buf) - 1))
{
- ifdstream ifs (move (sock),
- fdstream_mode::non_blocking,
- ostream::badbit);
-
- char buf[256];
- for (streamsize n (0), m (0);
- n == 0 || m != 0;
- m = ifs.readsome (buf, sizeof (buf) - 1))
+ if (m != 0)
{
- if (m != 0)
- {
- n += m;
+ n += m;
- //buf[m] = '\0';
- //text << buf;
- }
+ //buf[m] = '\0';
+ //text << buf;
}
+ }
- sock = ifs.release ();
- };
-
- // Read QEMU welcome.
- //
- readsome ();
+ sock = ifs.release ();
+ };
- // Write our command.
- //
- {
- ofdstream ofs (move (sock), fdstream_mode::blocking);
- ofs << c << endl;
- sock = ofs.release ();
- }
+ // Read QEMU welcome.
+ //
+ readsome ();
- // Read QEMU reply (may hit eof).
- //
- readsome ();
- return;
- }
- catch (const system_error& e)
+ // Write our command.
+ //
{
- fail (fh) << "unable to communicate with qemu monitor: " << e;
+ ofdstream ofs (move (sock), fdstream_mode::blocking);
+ ofs << c << endl;
+ sock = ofs.release ();
}
+
+ // Read QEMU reply (may hit eof).
+ //
+ readsome ();
}
unique_ptr<machine>