Show running processes using deleted files.
authorJán Kupec <jkupec@suse.cz>
Thu, 3 Sep 2009 17:11:11 +0000 (19:11 +0200)
committerJán Kupec <jkupec@suse.cz>
Thu, 3 Sep 2009 17:11:11 +0000 (19:11 +0200)
- fate #300763

doc/zypper.8
src/Summary.cc
src/Summary.h
src/solve-commit.cc

index 0c05bbb..51ff8a3 100644 (file)
@@ -1429,6 +1429,29 @@ This option serves mainly for testing purposes. It will cause zypper to act
 as if there were no packages installed in the system. Use with caution as you
 can damage your system using this option. 
 
+.SH "NOTES"
+.TP
+.B Notification About Running Processes Using Deleted Files
+After each upgrade or removal of packages Zypper checks whether
+there are any runing processes that may be using files recently
+deleted by an upgrade or package removal. If such processes are
+found, zypper will list them in a table having the following columns:
+
+* PID\ \ \ \ \ \ ID of the process
+.br
+* PPID\ \ \ \ \ ID of the parent process
+.br
+* UID\ \ \ \ \ \ ID of the user running the process
+.br
+* Login\ \ \ \ login name of the user running the process
+.br
+* Command\ \ command used to execute the process
+.br
+* Service\ \ guessed name of the service. If an init script exists for this
+ \ \ \ \ \ \ \ \ \ \ service, you can do "rcservicename restart" to restart it.
+.br
+* Files\ \ \ \ the list of the deleted files
+
 .SH "FILES"
 .TP
 .B /etc/zypp/zypper.conf, $HOME/.zypper.conf
index 73b9e57..e727249 100644 (file)
@@ -237,6 +237,18 @@ unsigned Summary::packagesToRemove() const
 
 // --------------------------------------------------------------------------
 
+unsigned Summary::packagesToUpgrade() const
+{
+  // total packages to remove (packages only - patches, patterns, and products
+  // are virtual; srcpackages do not get removed by zypper)
+  KindToResPairSet::const_iterator it = toupgrade.find(ResKind::package);
+  if (it != toupgrade.end())
+    return it->second.size();
+  return 0;
+}
+
+// --------------------------------------------------------------------------
+
 void Summary::writeResolvableList(ostream & out, const ResPairSet & resolvables)
 {
   // find multi-version packages
index 7cada03..40f8367 100644 (file)
@@ -78,9 +78,11 @@ public:
   void writePackageCounts(std::ostream & out);
   void writeDownloadAndInstalledSizeSummary(std::ostream & out);
 
+
   unsigned packagesToGetAndInstall() const
   { return _inst_pkg_total; }
   unsigned packagesToRemove() const;
+  unsigned packagesToUpgrade() const;
   const zypp::ByteCount & toDownload() const
   { return _todownload; }
   const zypp::ByteCount & installedSizeChange() const
index 2b0cb45..db39a9d 100755 (executable)
 #include "zypp/FileChecker.h"
 
 #include "zypp/media/MediaException.h"
+#include "zypp/misc/CheckAccessDeleted.h"
 
 #include "misc.h"              // confirm_licenses
 #include "utils/misc.h"
 #include "utils/prompt.h"      // Continue? and solver problem prompt
 #include "utils/pager.h"       // to view the summary
+#include "Table.h"             // for process list in suggest_restart_services
 #include "Summary.h"
 
 #include "solve-commit.h"
@@ -370,6 +372,78 @@ ZYppCommitPolicy get_commit_policy(Zypper & zypper)
   return policy;
 }
 
+/** fate #300763
+ * This is called after each commit to show running processes that use
+ * libraries or other files that have been removed since their execution.
+ * This is particularly useful after zypper remove or zypper update.
+ */
+static void suggest_restart_services(Zypper & zypper)
+{
+  zypper.out().info(
+      _("Checking for running processes using deleted libraries..."), Out::HIGH);
+  zypp::CheckAccessDeleted checker(false); // wait for explicit call to check()
+  try
+  {
+    checker.check();
+  }
+  catch(const zypp::Exception & e)
+  {
+    if (zypper.out().verbosity() > Out::NORMAL)
+      zypper.out().error(e, _("Check failed:"));
+  }
+
+  Table t;
+  t.allowAbbrev(6);
+  TableHeader th;
+  // process ID
+  th << _("PID");
+  // parent process ID
+  th << _("PPID");
+  // process user ID
+  th << _("UID");
+  // process login name
+  th << _("Login");
+  // process command name
+  th << _("Command");
+  // "/etc/init.d/ script that might be used to restart the command (guessed)
+  th << _("Service");
+  // "list of deleted files or libraries accessed"
+  th << _("Files");
+  t << th;
+
+  for_( it, checker.begin(), checker.end() )
+  {
+    TableRow tr;
+    vector<string>::const_iterator fit = it->files.begin();
+    tr << it->pid << it->ppid << it->puid << it->login << it->command
+      << it->service() << (fit != it->files.end() ? *fit : "");
+    t << tr;
+    for (; fit != it->files.end(); ++fit)
+    {
+      TableRow tr1;
+      tr1 << "" << "" << "" << "" << "" << "" << *fit;
+      t << tr1;
+    }
+  }
+
+  if (t.empty())
+  {
+    zypper.out().info(_("No such processes found."), Out::HIGH);
+  }
+  else
+  {
+    cout << endl;
+    zypper.out().info(_("The following running processes use deleted files:"));
+    cout << endl;
+    cout << t << endl;
+    zypper.out().info(_("You may wish to restart these processes."));
+    zypper.out().info(str::form(
+        _("See '%s' for information about the meaning of values"
+          " in the above table."),
+        "man zypper"));
+  }
+}
+
 // ----------------------------------------------------------------------------
 // commit
 // ----------------------------------------------------------------------------
@@ -723,6 +797,10 @@ void solve_and_commit (Zypper & zypper)
               " needed patches."),
             Out::QUIET, Out::TYPE_NORMAL); // don't show this to machines
         }
+
+        // check for running services
+        if (summary.packagesToRemove() && summary.packagesToUpgrade())
+          suggest_restart_services(zypper);
       }
     }
     // noting to do