From 0238e9ef50f115d98cf860a476bff8b5edff12ff Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 6 Aug 2017 21:10:06 +0200 Subject: Handle the case where machine is shutdown/rebooted from within --- bbot/agent/machine.cxx | 149 +++++++++++++++++++++++++------------------------ 1 file 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 (&addr), - sizeof (addr)) == -1) - throw_system_error (errno); + if (connect (sock.get (), + reinterpret_cast (&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 -- cgit v1.1