borgbackup / borg

Deduplicating archiver with compression and authenticated encryption.
https://www.borgbackup.org/
Other
10.73k stars 734 forks source link

fix Ctrl-C / SIGINT behaviour for pyinstaller-made binaries, fixes #8155 (1.2-maint) #8162

Closed ThomasWaldmann closed 3 months ago

codecov-commenter commented 3 months ago

Codecov Report

Attention: Patch coverage is 20.00000% with 8 lines in your changes are missing coverage. Please review.

Project coverage is 82.14%. Comparing base (04c8bc6) to head (caba23f). Report is 3 commits behind head on 1.2-maint.

Files Patch % Lines
src/borg/helpers/process.py 20.00% 8 Missing :warning:

:exclamation: Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## 1.2-maint #8162 +/- ## ============================================= - Coverage 82.18% 82.14% -0.04% ============================================= Files 38 38 Lines 10831 10838 +7 Branches 2077 2079 +2 ============================================= + Hits 8901 8903 +2 - Misses 1368 1373 +5 Partials 562 562 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

jdchristensen commented 3 months ago

This might work to slightly simplify the logic. Untested.

# Set-up:
        self.debounce_interval = 20000000  # ns
       self.last = None

# handler:

        # Ignore a SIGINT if it comes too quickly after the last one, e.g. because it
        # was caused by the same Ctrl-C key press and a parent process forwarded it to us.
       # This can easily happen for the pyinstaller-made binaries because the bootloader
       # process and the borg process are in same process group (see #8155), but maybe also
       # under other circumstances.
       now = time.monotonic_ns()
    if self.last is None: # first SIGINT
            self.last = now
        self._sig_int_triggered = True
            self._action_triggered = True
        elif now - self.last >= self.debounce_interval: # second SIGINT
            # restore the original signal handler for the 3rd+ SIGINT -
            # this implies that this handler here loses control!
            self.__exit__(None, None, None)
            # handle 2nd SIGINT like the default handler would do it:
            raise KeyboardInterrupt  # python docs say this might show up at an arbitrary place.
ThomasWaldmann commented 3 months ago

@jdchristensen ah, good idea. I just had added a slight fix to not assume zero-based monotonic time, but your suggestion is even better.

ThomasWaldmann commented 3 months ago

@jdchristensen gave it a practical test under linux with a freshly made binary: works!