Browse Source

Merge pull request #9085 from ThomasWaldmann/mount-show-rc-master

mount --show-rc: display main process rc, fixes #8308
TW 3 days ago
parent
commit
140ff56135

+ 4 - 16
src/borg/archiver/__init__.py

@@ -34,7 +34,7 @@ try:
     from ._common import Highlander
     from .. import __version__
     from ..constants import *  # NOQA
-    from ..helpers import EXIT_WARNING, EXIT_ERROR, EXIT_SIGNAL_BASE, classify_ec
+    from ..helpers import EXIT_WARNING, EXIT_ERROR, EXIT_SIGNAL_BASE
     from ..helpers import Error, CommandError, get_ec, modern_ec
     from ..helpers import add_warning, BorgWarning, BackupWarning
     from ..helpers import format_file_size
@@ -686,21 +686,9 @@ def main():  # pragma: no cover
         if tb:
             logger.log(tb_log_level, tb)
         if args.show_rc:
-            rc_logger = logging.getLogger("borg.output.show-rc")
-            exit_msg = "terminating with %s status, rc %d"
-            try:
-                ec_class = classify_ec(exit_code)
-            except ValueError:
-                rc_logger.error(exit_msg % ("abnormal", exit_code or 666))
-            else:
-                if ec_class == "success":
-                    rc_logger.info(exit_msg % (ec_class, exit_code))
-                elif ec_class == "warning":
-                    rc_logger.warning(exit_msg % (ec_class, exit_code))
-                elif ec_class == "error":
-                    rc_logger.error(exit_msg % (ec_class, exit_code))
-                elif ec_class == "signal":
-                    rc_logger.error(exit_msg % (ec_class, exit_code))
+            from ..helpers import do_show_rc
+
+            do_show_rc(exit_code)
         sys.exit(exit_code)
 
 

+ 1 - 1
src/borg/archiver/mount_cmds.py

@@ -40,7 +40,7 @@ class MountMixIn:
             operations = FuseOperations(manifest, args, cached_repo)
             logger.info("Mounting filesystem")
             try:
-                operations.mount(args.mountpoint, args.options, args.foreground)
+                operations.mount(args.mountpoint, args.options, args.foreground, args.show_rc)
             except RuntimeError:
                 # Relevant error message already printed to stderr by FUSE
                 raise RTError("FUSE mount failed")

+ 2 - 2
src/borg/fuse.py

@@ -489,7 +489,7 @@ class FuseOperations(llfuse.Operations, FuseBackend):
         )
         self.decrypted_repository.log_instrumentation()
 
-    def mount(self, mountpoint, mount_options, foreground=False):
+    def mount(self, mountpoint, mount_options, foreground=False, show_rc=False):
         """Mount filesystem on *mountpoint* with *mount_options*."""
 
         def pop_option(options, key, present, not_present, wanted_type, int_base=0):
@@ -562,7 +562,7 @@ class FuseOperations(llfuse.Operations, FuseBackend):
             if isinstance(self.repository_uncached, RemoteRepository):
                 daemonize()
             else:
-                with daemonizing() as (old_id, new_id):
+                with daemonizing(show_rc=show_rc) as (old_id, new_id):
                     # local repo: the locking process' PID is changing, migrate it:
                     logger.debug("fuse: mount local repo, going to background: migrating lock.")
                     self.repository_uncached.migrate_lock(old_id, new_id)

+ 28 - 0
src/borg/helpers/__init__.py

@@ -6,6 +6,7 @@ package, which are imported here for compatibility.
 """
 
 import os
+import logging
 from typing import List
 from collections import namedtuple
 
@@ -172,3 +173,30 @@ def get_reset_ec(ec=None):
     rc = get_ec(ec)
     init_ec_warnings()
     return rc
+
+
+def do_show_rc(exit_code):
+    """Log the program return code using the dedicated 'borg.output.show-rc' logger.
+
+    Uses INFO/WARNING/ERROR levels depending on the classified exit code.
+
+    This helper is robust: it swallows any exceptions to avoid interfering with
+    program exit behavior. Callers do not need to guard it with try/except.
+    """
+    try:
+        exit_msg = "terminating with %s status, rc %d"
+        rc_logger = logging.getLogger("borg.output.show-rc")
+        try:
+            ec_class = classify_ec(exit_code)
+        except ValueError:
+            rc_logger.error(exit_msg % ("abnormal", exit_code or 666))
+        else:
+            if ec_class == "success":
+                rc_logger.info(exit_msg % (ec_class, exit_code))
+            elif ec_class == "warning":
+                rc_logger.warning(exit_msg % (ec_class, exit_code))
+            elif ec_class in ("error", "signal"):
+                rc_logger.error(exit_msg % (ec_class, exit_code))
+    except Exception:  # nosec B110
+        # Never let logging issues interfere with exit behaviour
+        pass

+ 8 - 1
src/borg/helpers/process.py

@@ -63,7 +63,7 @@ def daemonize():
 
 
 @contextlib.contextmanager
-def daemonizing(*, timeout=5):
+def daemonizing(*, timeout=5, show_rc=False):
     """Like daemonize(), but as a context manager.
 
     The with-body is executed in the background process,
@@ -112,6 +112,13 @@ def daemonizing(*, timeout=5):
                     logger.warning("Daemonizing: Background process did not respond (timeout). Is it alive?")
                     exit_code = EXIT_WARNING
                 finally:
+                    # Before terminating the foreground process, honor --show-rc by logging the rc here as well.
+                    # This is mostly a consistency fix and not very useful considering that the main action
+                    # happens in the daemon process.
+                    if show_rc:
+                        from ..helpers import do_show_rc
+
+                        do_show_rc(exit_code)
                     # Don't call with-body, but die immediately!
                     # return would be sufficient, but we want to pass the exit code.
                     raise _ExitCodeException(exit_code)