From 99f5dfbde7590048eabecfff463850ec8cf5a989 Mon Sep 17 00:00:00 2001 From: David Kocik <kocikdav@gmail.com> Date: Mon, 21 Dec 2020 14:53:57 +0100 Subject: [PATCH] Added error-checking for child.wait() call during removable drive ejection (to prevent #5507) Mark Ejection as failed if the wait() function fails. It seems that it is not simply possible to retrieve the exit code of the process in that case (although it usually finishes sucessfully). --- src/slic3r/GUI/RemovableDriveManager.cpp | 28 +++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/RemovableDriveManager.cpp b/src/slic3r/GUI/RemovableDriveManager.cpp index bc733ee9f..ec69bb198 100644 --- a/src/slic3r/GUI/RemovableDriveManager.cpp +++ b/src/slic3r/GUI/RemovableDriveManager.cpp @@ -277,14 +277,15 @@ void RemovableDriveManager::eject_drive() //std::cout<<"Ejecting "<<(*it).name<<" from "<< correct_path<<"\n"; // there is no usable command in c++ so terminal command is used instead // but neither triggers "succesful safe removal messege" - BOOST_LOG_TRIVIAL(info) << "Ejecting started"; - boost::process::ipstream istd_err; - boost::process::child child( + + BOOST_LOG_TRIVIAL(info) << "Ejecting started"; + boost::process::ipstream istd_err; + boost::process::child child( #if __APPLE__ boost::process::search_path("diskutil"), "eject", correct_path.c_str(), (boost::process::std_out & boost::process::std_err) > istd_err); - //Another option how to eject at mac. Currently not working. - //used insted of system() command; - //this->eject_device(correct_path); + //Another option how to eject at mac. Currently not working. + //used insted of system() command; + //this->eject_device(correct_path); #else boost::process::search_path("umount"), correct_path.c_str(), (boost::process::std_out & boost::process::std_err) > istd_err); #endif @@ -293,8 +294,19 @@ void RemovableDriveManager::eject_drive() BOOST_LOG_TRIVIAL(trace) << line; } // wait for command to finnish (blocks ui thread) - child.wait(); - int err = child.exit_code(); + std::error_code ec; + child.wait(ec); + if (ec) { + // The wait call can fail, as it did in https://github.com/prusa3d/PrusaSlicer/issues/5507 + // It can happen even in cases where the eject is sucessful, but better report it as failed. + // We did not find a way to reliably retrieve the exit code of the process. + BOOST_LOG_TRIVIAL(error) << "boost::process::child::wait() failed during Ejection. State of Ejection is unknown. Error code: " << ec.value(); + assert(m_callback_evt_handler); + if (m_callback_evt_handler) + wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>(*it_drive_data, false))); + return; + } + int err = child.exit_code(); if (err) { BOOST_LOG_TRIVIAL(error) << "Ejecting failed. Exit code: " << err; assert(m_callback_evt_handler);