diff --git a/common/rinstallprogress.cc b/common/rinstallprogress.cc index 042e4a5a..bbbd1838 100644 --- a/common/rinstallprogress.cc +++ b/common/rinstallprogress.cc @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -70,13 +71,12 @@ const char *RInstallProgress::getResultStr(pkgPackageManager::OrderResult res) return "Unknown install result."; } -pkgPackageManager::OrderResult RInstallProgress::start(pkgPackageManager *pm, - int numPackages, - int numPackagesTotal) +std::optional RInstallProgress::start( + pkgPackageManager *pm, + int numPackages, + int numPackagesTotal) { pkgPackageManager::OrderResult res; - int ret; - pid_t _child_id; // cout << "RInstallProgress::start()" << endl; @@ -136,13 +136,22 @@ pkgPackageManager::OrderResult RInstallProgress::start(pkgPackageManager *pm, } #endif - startUpdate(); - while (waitpid(_child_id, &ret, WNOHANG) == 0) - updateInterface(); + return std::nullopt; +} - res = (pkgPackageManager::OrderResult)WEXITSTATUS(ret); +std::optional RInstallProgress::poll() +{ + int ret = 0; + pid_t pid = waitpid(_child_id, &ret, WNOHANG); + if (pid == 0) { + return std::nullopt; + } - finishUpdate(); + // WEXITSTATUS of a signal-killed child is 0, i.e. Completed + pkgPackageManager::OrderResult res = + (pid > 0 && WIFEXITED(ret)) + ? (pkgPackageManager::OrderResult)WEXITSTATUS(ret) + : pkgPackageManager::Failed; #ifdef HAVE_RPM close(_childin); @@ -150,5 +159,3 @@ pkgPackageManager::OrderResult RInstallProgress::start(pkgPackageManager *pm, return res; } - -// vim:sts=4:sw=4 diff --git a/common/rinstallprogress.h b/common/rinstallprogress.h index 7a274b3c..aeeb5f86 100644 --- a/common/rinstallprogress.h +++ b/common/rinstallprogress.h @@ -28,11 +28,14 @@ #include +#include #include class RInstallProgress { protected: + pid_t _child_id; + int _stdout; int _stderr; int _childin; @@ -49,6 +52,21 @@ class RInstallProgress static std::string errorMsg; static std::string incompleteMsg; + // get a str feed to the user with the result of the install run + virtual const char *getResultStr(pkgPackageManager::OrderResult); + + public: + // std::nullopt means the child is still running; a plain OrderResult + // would be ambiguous here as Incomplete is a real child result + // (media swap needed) + virtual std::optional start( + pkgPackageManager *pm, + int numPackages = 0, + int numPackagesTotal = 0); + virtual std::optional poll(); + virtual void finish() + {} + virtual void startUpdate() {} virtual void updateInterface() @@ -56,14 +74,6 @@ class RInstallProgress virtual void finishUpdate() {} - public: - // get a str feed to the user with the result of the install run - virtual const char *getResultStr(pkgPackageManager::OrderResult); - virtual pkgPackageManager::OrderResult start(pkgPackageManager *pm, - int numPackages = 0, - int numPackagesTotal = 0); - - RInstallProgress() : _donePackagesTotal(0), _numPackagesTotal(0), _updateFinished(false) {} diff --git a/common/rpackagelister.cc b/common/rpackagelister.cc index 40a4c6be..246a1ade 100644 --- a/common/rpackagelister.cc +++ b/common/rpackagelister.cc @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -1492,23 +1493,25 @@ bool RPackageLister::commitChanges(pkgAcquireStatus *status, _("Ignoring invalid record(s) in sources.list file!")); } - pkgPackageManager *rPM; - rPM = _system->CreatePM(_cache->deps()); + std::unique_ptr rPM{_system->CreatePM(_cache->deps())}; if (!rPM->GetArchives(&fetcher, _cache->list(), _records) || - _error->PendingError()) - goto gave_wood; + _error->PendingError()) { + return false; + } // ripped from apt-get while (1) { bool Transient = false; #ifdef HAVE_RPM - if (fetcher.Run() == pkgAcquire::Failed) - goto gave_wood; + if (fetcher.Run() == pkgAcquire::Failed) { + return false; + } #else - if (fetcher.Run(50000) == pkgAcquire::Failed) - goto gave_wood; + if (fetcher.Run(50000) == pkgAcquire::Failed) { + return false; + } #endif string serverError; @@ -1560,11 +1563,9 @@ bool RPackageLister::commitChanges(pkgAcquireStatus *status, if (Failed) { string message; - if (Transient) - goto gave_wood; - - if (numPackages == 0) - goto gave_wood; + if (Transient || numPackages == 0) { + return false; + } message = _("Some of the packages could not be retrieved from the " "server(s).\n"); @@ -1572,13 +1573,14 @@ bool RPackageLister::commitChanges(pkgAcquireStatus *status, message += "(" + serverError + ")\n"; message += _("Do you want to continue, ignoring these packages?"); - if (!_userDialog->confirm(message.c_str())) - goto gave_wood; + if (!_userDialog->confirm(message.c_str())) { + return false; + } } // Try to deal with missing package files if (Failed == true && rPM->FixMissing() == false) { _error->Error(_("Unable to correct missing packages")); - goto gave_wood; + return false; } // need this so that we first fetch everything and then install (for CDs) if (Transient == false || @@ -1590,12 +1592,20 @@ bool RPackageLister::commitChanges(pkgAcquireStatus *status, } _system->UnLockInner(); - pkgPackageManager::OrderResult Res = - iprog->start(rPM, numPackages, numPackagesTotal); + std::optional Res; + Res = iprog->start(rPM.get(), numPackages, numPackagesTotal); + if (!Res.has_value()) { + iprog->startUpdate(); + while (!(Res = iprog->poll()).has_value()) { + iprog->updateInterface(); + } + iprog->finishUpdate(); + } _system->LockInner(); - if (Res == pkgPackageManager::Failed || _error->PendingError()) { - if (Transient == false) - goto gave_wood; + if (*Res == pkgPackageManager::Failed || _error->PendingError()) { + if (Transient == false) { + return false; + } Ret = false; // TODO: We must not discard errors here. The right // solution is to use an "error stack", as @@ -1603,7 +1613,7 @@ bool RPackageLister::commitChanges(pkgAcquireStatus *status, //_error->DumpErrors(); _error->Discard(); } - if (Res == pkgPackageManager::Completed) + if (*Res == pkgPackageManager::Completed) break; numPackages = 0; @@ -1611,8 +1621,9 @@ bool RPackageLister::commitChanges(pkgAcquireStatus *status, // Reload the fetcher object and loop again for media swapping fetcher.Shutdown(); - if (!rPM->GetArchives(&fetcher, _cache->list(), _records)) - goto gave_wood; + if (!rPM->GetArchives(&fetcher, _cache->list(), _records)) { + return false; + } } // cout << _("Finished.")<FindB("Synaptic::Log::Changes", true)) writeCommitLog(); - delete rPM; return Ret; - -gave_wood: - delete rPM; - return false; } void RPackageLister::writeCommitLog() diff --git a/gtk/rgdebinstallprogress.cc b/gtk/rgdebinstallprogress.cc index 0bb8daab..3fc37614 100644 --- a/gtk/rgdebinstallprogress.cc +++ b/gtk/rgdebinstallprogress.cc @@ -42,15 +42,9 @@ # include # include # include -# include -# include -# include -# include -# include # include -# include # include -# include +# include # include # include # include @@ -71,7 +65,8 @@ void RGDebInstallProgress::child_exited(VteTerminal *vteterminal, { RGDebInstallProgress *me = (RGDebInstallProgress *)data; - me->res = (pkgPackageManager::OrderResult)WEXITSTATUS(ret); + me->res = WIFEXITED(ret) ? (pkgPackageManager::OrderResult)WEXITSTATUS(ret) + : pkgPackageManager::Failed; me->child_has_exited = true; } @@ -481,7 +476,7 @@ gboolean RGDebInstallProgress::key_press_event(GtkWidget *widget, RGDebInstallProgress *me = (RGDebInstallProgress *)user_data; // user pressed ctrl-c - if (event->keyval == GDK_c && event->state & GDK_CONTROL_MASK) { + if (event->keyval == GDK_KEY_c && event->state & GDK_CONTROL_MASK) { gchar *summary = _("Ctrl-c pressed"); char *msg = _("This will abort the operation and may leave the system " "in a broken state. Are you sure you want to do that?"); @@ -501,15 +496,15 @@ gboolean RGDebInstallProgress::key_press_event(GtkWidget *widget, case GTK_RESPONSE_NO: return true; } - } else if (event->keyval == GDK_C && + } else if (event->keyval == GDK_KEY_C && event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) { // ctrl+shift+C copy to clipboard to mimic gnome-terminal behavior me->terminalAction(me->_term, EDIT_COPY); return true; - } else if (event->keyval == GDK_a && event->state & GDK_CONTROL_MASK) { + } else if (event->keyval == GDK_KEY_a && event->state & GDK_CONTROL_MASK) { me->terminalAction(me->_term, EDIT_SELECT_ALL); return true; - } else if (event->keyval == GDK_A && + } else if (event->keyval == GDK_KEY_A && event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) { me->terminalAction(me->_term, EDIT_SELECT_NONE); return true; @@ -664,7 +659,7 @@ void RGDebInstallProgress::updateInterface() } } -pkgPackageManager::OrderResult RGDebInstallProgress::start( +std::optional RGDebInstallProgress::start( pkgPackageManager *pm, int numPackages, int numPackagesTotal) @@ -675,7 +670,6 @@ pkgPackageManager::OrderResult RGDebInstallProgress::start( if (res == pkgPackageManager::Failed) return res; - int master; _child_id = forkpty(&master, NULL, NULL, NULL); if (_child_id < 0) { cerr << "vte_terminal_forkpty() failed. " << strerror(errno) << endl; @@ -744,11 +738,13 @@ pkgPackageManager::OrderResult RGDebInstallProgress::start( _numPackages = numPackages; _numPackagesTotal = numPackagesTotal; - startUpdate(); - while (!child_has_exited) - updateInterface(); + return std::nullopt; +} - finishUpdate(); +std::optional RGDebInstallProgress::poll() +{ + if (!child_has_exited) + return std::nullopt; ::close(_childin); ::close(master); diff --git a/gtk/rgdebinstallprogress.h b/gtk/rgdebinstallprogress.h index aa06398a..4c323e30 100644 --- a/gtk/rgdebinstallprogress.h +++ b/gtk/rgdebinstallprogress.h @@ -31,11 +31,9 @@ # include # include -# include -# include # include -# include # include +# include # include # include # include @@ -110,7 +108,7 @@ class RGDebInstallProgress : public RInstallProgress, public RGGtkBuilderWindow // last time something changed time_t last_term_action; - pid_t _child_id; + int master; pkgPackageManager::OrderResult res; bool child_has_exited; static void child_exited(VteTerminal *vteterminal, gint ret, gpointer data); @@ -119,15 +117,8 @@ class RGDebInstallProgress : public RInstallProgress, public RGGtkBuilderWindow GtkCssProvider *_cssProvider; protected: - virtual void startUpdate(); - virtual void updateInterface(); - virtual void finishUpdate(); virtual bool close(); - virtual pkgPackageManager::OrderResult start(pkgPackageManager *pm, - int numPackages = 0, - int totalPackages = 0); - virtual void prepare(RPackageLister *lister); void conffile(gchar *conffile, gchar *status); @@ -150,6 +141,16 @@ class RGDebInstallProgress : public RInstallProgress, public RGGtkBuilderWindow public: RGDebInstallProgress(RGMainWindow *main, RPackageLister *lister); virtual ~RGDebInstallProgress(); + + virtual std::optional start( + pkgPackageManager *pm, + int numPackages = 0, + int totalPackages = 0) override; + virtual std::optional poll() override; + + virtual void startUpdate() override; + virtual void updateInterface() override; + virtual void finishUpdate() override; }; #endif // WITH_DPKG_STATUSFD diff --git a/gtk/rgdummyinstallprogress.h b/gtk/rgdummyinstallprogress.h index 1e857fa2..8d2504ea 100644 --- a/gtk/rgdummyinstallprogress.h +++ b/gtk/rgdummyinstallprogress.h @@ -28,12 +28,11 @@ class RGDummyInstallProgress : public RInstallProgress { - protected: - virtual void startUpdate(); - virtual void updateInterface(); - virtual void finishUpdate(); - public: RGDummyInstallProgress() : RInstallProgress() {}; virtual ~RGDummyInstallProgress() {}; + + virtual void startUpdate() override; + virtual void updateInterface() override; + virtual void finishUpdate() override; }; diff --git a/gtk/rginstallprogress.cc b/gtk/rginstallprogress.cc index 4daf10e7..6704b262 100644 --- a/gtk/rginstallprogress.cc +++ b/gtk/rginstallprogress.cc @@ -36,13 +36,8 @@ #include #include #include -#include -#include -#include #include -#include #include -#include #include #include #include diff --git a/gtk/rginstallprogress.h b/gtk/rginstallprogress.h index 8937854b..35084e3a 100644 --- a/gtk/rginstallprogress.h +++ b/gtk/rginstallprogress.h @@ -28,7 +28,6 @@ #include "rinstallprogress.h" #include -#include #include #include @@ -86,13 +85,13 @@ class RGInstallProgress : public RInstallProgress, public RGGtkBuilderWindow GtkCssProvider *_cssProviderBold; protected: - virtual void startUpdate(); - virtual void updateInterface(); - virtual void finishUpdate(); - virtual void prepare(RPackageLister *lister); public: RGInstallProgress(RGMainWindow *main, RPackageLister *lister); ~RGInstallProgress(); + + virtual void startUpdate() override; + virtual void updateInterface() override; + virtual void finishUpdate() override; }; diff --git a/gtk/rgmainwindow.cc b/gtk/rgmainwindow.cc index 8f8d1729..9d4e433c 100644 --- a/gtk/rgmainwindow.cc +++ b/gtk/rgmainwindow.cc @@ -51,6 +51,8 @@ #include "rgsummarywindow.h" #include "rgtaskswin.h" #include "rgterminstallprogress.h" +#include "rginstallprogress.h" +#include "rgdummyinstallprogress.h" #include "rguserdialog.h" #include "rgutils.h" #include "rgwindow.h" @@ -2702,9 +2704,8 @@ void RGMainWindow::cbProceedClicked(GSimpleAction *action, bool UseTerminal = true; # endif // DPKG # endif // HAVE_RPM - RGTermInstallProgress *term = NULL; if (_config->FindB("Synaptic::UseTerminal", UseTerminal) == true) - iprogress = term = new RGTermInstallProgress(me); + iprogress = new RGTermInstallProgress(me); else #endif // HAVE_TERMINAL @@ -2723,16 +2724,7 @@ void RGMainWindow::cbProceedClicked(GSimpleAction *action, // bool result = me->_lister->commitChanges(fprogress, iprogress); me->_lister->commitChanges(fprogress, iprogress); - // FIXME: move this into the terminal class -#ifdef HAVE_TERMINAL - // wait until the term dialog is closed - if (term != NULL) { - while (gtk_widget_get_visible(GTK_WIDGET(term->window()))) { - RGFlushInterface(); - usleep(100000); - } - } -#endif + iprogress->finish(); delete fprogress; me->_fetchProgress = NULL; delete iprogress; diff --git a/gtk/rgterminstallprogress.cc b/gtk/rgterminstallprogress.cc index 03a063b4..e46cc274 100644 --- a/gtk/rgterminstallprogress.cc +++ b/gtk/rgterminstallprogress.cc @@ -41,12 +41,9 @@ # include # include # include -# include -# include -# include # include # include -# include +# include # include # include # include @@ -110,7 +107,8 @@ void RGTermInstallProgress::child_exited(VteTerminal *vteterminal, { RGTermInstallProgress *me = (RGTermInstallProgress *)data; - me->res = (pkgPackageManager::OrderResult)WEXITSTATUS(ret); + me->res = WIFEXITED(ret) ? (pkgPackageManager::OrderResult)WEXITSTATUS(ret) + : pkgPackageManager::Failed; me->child_has_exited = true; } @@ -184,7 +182,7 @@ bool RGTermInstallProgress::close() } -pkgPackageManager::OrderResult RGTermInstallProgress::start( +std::optional RGTermInstallProgress::start( pkgPackageManager *pm, int numPackages, int numPackagesTotal) @@ -195,7 +193,6 @@ pkgPackageManager::OrderResult RGTermInstallProgress::start( if (res == pkgPackageManager::Failed) return res; - int master; _child_id = forkpty(&master, NULL, NULL, NULL); if (_child_id < 0) { cerr << "Internal Error: impossible to fork children. Synaptics is going " @@ -229,13 +226,15 @@ pkgPackageManager::OrderResult RGTermInstallProgress::start( // we can set it? vte_terminal_watch_child(VTE_TERMINAL(_term), _child_id); - startUpdate(); + return std::nullopt; +} + +std::optional RGTermInstallProgress::poll() +{ // make sure that the child has really exited and we catched the // return code - while (!child_has_exited) - updateInterface(); - - finishUpdate(); + if (!child_has_exited) + return std::nullopt; ::close(master); @@ -253,7 +252,12 @@ void RGTermInstallProgress::updateInterface() } } +void RGTermInstallProgress::finish() +{ + while (gtk_widget_get_visible(GTK_WIDGET(window()))) { + RGFlushInterface(); + usleep(100000); + } +} #endif - -// vim:sts=3:sw=3 diff --git a/gtk/rgterminstallprogress.h b/gtk/rgterminstallprogress.h index 9a7c7ffc..08085494 100644 --- a/gtk/rgterminstallprogress.h +++ b/gtk/rgterminstallprogress.h @@ -30,8 +30,8 @@ # include "rinstallprogress.h" # include -# include # include +# include # include # include @@ -45,26 +45,29 @@ class RGTermInstallProgress : public RInstallProgress, public RGGtkBuilderWindow GtkWidget *_closeB; GtkWidget *_closeOnF; + int master; pkgPackageManager::OrderResult res; protected: bool child_has_exited; static void child_exited(VteTerminal *vteterminal, gint ret, gpointer data); - virtual void startUpdate(); - virtual void updateInterface(); - virtual void finishUpdate(); static void stopShell(GtkWidget *self, void *data); virtual bool close(); - pid_t _child_id; - public: RGTermInstallProgress(RGMainWindow *main); ~RGTermInstallProgress() {}; - virtual pkgPackageManager::OrderResult start(pkgPackageManager *pm, - int numPackages = 0, - int totalPackages = 0); + virtual std::optional start( + pkgPackageManager *pm, + int numPackages = 0, + int totalPackages = 0) override; + virtual std::optional poll() override; + virtual void finish() override; + + virtual void startUpdate() override; + virtual void updateInterface() override; + virtual void finishUpdate() override; }; #endif /* HAVT_TERMINAL */