Jelajahi Sumber

mount --show-rc: display main process rc, fixes #8308

when borg mount is used without -f/--foreground (so that the FUSE
borg process was started daemonized in the background), it did not
display the rc of the main process, even when --show-rc was used.

now it does display the rc of the main process.

note that this is rather a consistency fix than being super useful,
because the main "action" happens in the background daemon process,
not in the main process.
Thomas Waldmann 1 Minggu lalu
induk
melakukan
702de47197
4 mengubah file dengan 40 tambahan dan 19 penghapusan
  1. 3 16
      src/borg/archiver.py
  2. 2 2
      src/borg/fuse.py
  3. 28 0
      src/borg/helpers/__init__.py
  4. 7 1
      src/borg/helpers/process.py

+ 3 - 16
src/borg/archiver.py

@@ -1461,7 +1461,7 @@ class Archiver:
             operations = FuseOperations(key, repository, 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")
@@ -5678,21 +5678,8 @@ 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)
 
 

+ 2 - 2
src/borg/fuse.py

@@ -484,7 +484,7 @@ class FuseOperations(llfuse.Operations, FuseBackend):
                      format_file_size(sum(len(chunk) for key, chunk in self.data_cache.items())))
         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):
@@ -556,7 +556,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

@@ -5,6 +5,7 @@ Code used to be in borg/helpers.py but was split into modules in this
 package, which are imported here for compatibility.
 """
 from contextlib import contextmanager
+import logging
 
 from .checks import *  # NOQA
 from .datastruct import *  # NOQA
@@ -150,3 +151,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:
+        # Never let logging issues interfere with exit behaviour
+        pass

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

@@ -62,7 +62,7 @@ def daemonize():
 
 
 @contextlib.contextmanager
-def daemonizing(*, timeout=5):
+def daemonizing(*, timeout=5, show_rc=False):
     """Like daemonize(), but as context manager.
 
     The with-body is executed in the background process,
@@ -107,6 +107,12 @@ 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)