# Buggy code
def check_pids(curmir_incs):
    """Check PIDs in curmir markers to make sure rdiff-backup not running"""
    pid_re = re.compile(r"^PID\s*([0-9]+)", re.I | re.M)

    def extract_pid(curmir_rp):
        """Return process ID from a current mirror marker, if any"""
        match = pid_re.search(curmir_rp.get_string())
        if not match:
            return None
        else:
            return int(match.group(1))

    def pid_running(pid):
        """Return True if we know if process with pid is currently running,
        False if it isn't running, and None if we don't know for sure."""
        if os.name == "nt":
            import win32api
            import win32con
            import pywintypes

            process = None
            try:
                process = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, 0, pid)
            except pywintypes.error as error:
                if error[0] == 87:
                    return False
                else:
                    msg = "Warning: unable to check if PID %d still running"
                    log.Log(msg % pid, 2)
                    return None  # we don't know if the process is running
            else:
                if process:
                    win32api.CloseHandle(process)
                    return True
                else:
                    return False
        else:
            try:
                os.kill(pid, 0)
            except ProcessLookupError:  # errno.ESRCH - pid doesn't exist
                return False
            except OSError:  # any other OS error
                log.Log("Warning: unable to check if PID %d still running" % (pid,), 2)
                return None  # we don't know if the process is still running
            else:  # the process still exists
                return True

    for curmir_rp in curmir_incs:
        assert curmir_rp.conn is Globals.local_connection, (
            "Function must be called locally not over '{conn}'.".format(
                conn=curmir_rp.conn
            )
        )
        pid = extract_pid(curmir_rp)
        # FIXME differentiate between don't know and know and handle err.errno == errno.EPERM:
        # EPERM clearly means there's a process to deny access to with OSError
        if pid is not None and pid_running(pid):
            log.Log.FatalError(
                """It appears that a previous rdiff-backup session with process
id %d is still running.  If two different rdiff-backup processes write
the same repository simultaneously, data corruption will probably
result.  To proceed with regress anyway, rerun rdiff-backup with the
--force option."""
                % (pid,)
            )


# Traceback (MemoryError)
vagrant@WIN-4SPEID5E7R8 C:\Users\vagrant\Develop\rdiff-backup>rmdir /s /q \temp\bla

vagrant@WIN-4SPEID5E7R8 C:\Users\vagrant\Develop\rdiff-backup>rdiff-backup ..\rdiff-backup_testfiles\stattest1 \temp\bla

vagrant@WIN-4SPEID5E7R8 C:\Users\vagrant\Develop\rdiff-backup>rdiff-backup ..\rdiff-backup_testfiles\stattest2 \temp\bla
Exception '' raised of class '<class 'MemoryError'>':
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\robust.py", line 35, in check_common_error
return function(*args)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\Rdiff.py", line 98, in patch_local
return outrp.write_from_fileobj(patchfile)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\rpath.py", line 1462, in write_from_fileobj
copyfileobj(fp, outfp)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\rpath.py", line 79, in copyfileobj
inbuf = inputfp.read(blocksize)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\librsync.py", line 69, in read
self._add_to_outbuf_once()
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\librsync.py", line 98, in _add_to_outbuf_once
self.eof, len_inbuf_read, cycle_out = self.maker.cycle(self.inbuf)

Exception '' raised of class '<class 'MemoryError'>':
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\Main.py", line 399, in error_check_Main
_Main(arglist)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\Main.py", line 421, in _Main
return_val = _take_action(rps)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\Main.py", line 358, in _take_action
action_result = _action_backup(rps[0], rps[1])
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\Main.py", line 445, in _action_backup
backup.Mirror_and_increment(rpin, rpout, _incdir)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\backup.py", line 55, in Mirror_and_increment
DestS.patch_and_increment(dest_rpath, source_diffiter, inc_rpath)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\backup.py", line 281, in patch_and_increment
ITR(diff.index, diff)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\rorpiter.py", line 313, in __call__
last_branch.fast_process(*args)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\backup.py", line 781, in fast_process
if self._patch_to_temp(mirror_rp, diff_rorp, tf):
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\backup.py", line 617, in _patch_to_temp
elif not self._patch_diff_to_temp(basis_rp, diff_rorp, new):
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\backup.py", line 669, in _patch_diff_to_temp
self.error_handler, Rdiff.patch_local, (basis_rp, diff_rorp, new))
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\robust.py", line 35, in check_common_error
return function(*args)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\Rdiff.py", line 98, in patch_local
return outrp.write_from_fileobj(patchfile)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\rpath.py", line 1462, in write_from_fileobj
copyfileobj(fp, outfp)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\rpath.py", line 79, in copyfileobj
inbuf = inputfp.read(blocksize)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\librsync.py", line 69, in read
self._add_to_outbuf_once()
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\librsync.py", line 98, in _add_to_outbuf_once
self.eof, len_inbuf_read, cycle_out = self.maker.cycle(self.inbuf)

Traceback (most recent call last):
File "C:\Users\vagrant\Develop\rdiff-backup\build\scripts-3.7\rdiff-backup", line 32, in <module>
rdiff_backup.Main.error_check_Main(sys.argv[1:])
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\Main.py", line 399, in error_check_Main
_Main(arglist)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\Main.py", line 421, in _Main
return_val = _take_action(rps)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\Main.py", line 358, in _take_action
action_result = _action_backup(rps[0], rps[1])
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\Main.py", line 445, in _action_backup
backup.Mirror_and_increment(rpin, rpout, _incdir)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\backup.py", line 55, in Mirror_and_increment
DestS.patch_and_increment(dest_rpath, source_diffiter, inc_rpath)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\backup.py", line 281, in patch_and_increment
ITR(diff.index, diff)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\rorpiter.py", line 313, in __call__
last_branch.fast_process(*args)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\backup.py", line 781, in fast_process
if self._patch_to_temp(mirror_rp, diff_rorp, tf):
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\backup.py", line 617, in _patch_to_temp
elif not self._patch_diff_to_temp(basis_rp, diff_rorp, new):
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\backup.py", line 669, in _patch_diff_to_temp
self.error_handler, Rdiff.patch_local, (basis_rp, diff_rorp, new))
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\robust.py", line 35, in check_common_error
return function(*args)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\Rdiff.py", line 98, in patch_local
return outrp.write_from_fileobj(patchfile)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\rpath.py", line 1462, in write_from_fileobj
copyfileobj(fp, outfp)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\rpath.py", line 79, in copyfileobj
inbuf = inputfp.read(blocksize)
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\librsync.py", line 69, in read
self._add_to_outbuf_once()
File "C:\Users\vagrant\Develop\rdiff-backup\build\lib.win-amd64-3.7\rdiff_backup\librsync.py", line 98, in _add_to_outbuf_once
self.eof, len_inbuf_read, cycle_out = self.maker.cycle(self.inbuf)
MemoryError

# Fixed code
def check_pids(curmir_incs):
    """Check PIDs in curmir markers to make sure rdiff-backup not running"""
    pid_re = re.compile(r"^PID\s*([0-9]+)", re.I | re.M)

    def extract_pid(curmir_rp):
        """Return process ID from a current mirror marker, if any"""
        match = pid_re.search(curmir_rp.get_string())
        if not match:
            return None
        else:
            return int(match.group(1))

    def pid_running(pid):
        """Return True if we know if process with pid is currently running,
        False if it isn't running, and None if we don't know for sure."""
        if os.name == "nt":
            import win32api
            import win32con
            import pywintypes

            process = None
            try:
                process = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, 0, pid)
            except pywintypes.error as error:
                if error.winerror == 87:
                    # parameter incorrect, PID does not exist
                    return False
                elif error.winerror == 5:
                    # access denied, means nevertheless PID still exists
                    return True
                else:
                    msg = "Warning: unable to check if PID %d still running"
                    log.Log(msg % pid, 2)
                    return None  # we don't know if the process is running
            else:
                if process:
                    win32api.CloseHandle(process)
                    return True
                else:
                    return False
        else:
            try:
                os.kill(pid, 0)
            except ProcessLookupError:  # errno.ESRCH - pid doesn't exist
                return False
            except OSError:  # any other OS error
                log.Log("Warning: unable to check if PID %d still running" % (pid,), 2)
                return None  # we don't know if the process is still running
            else:  # the process still exists
                return True

    for curmir_rp in curmir_incs:
        assert curmir_rp.conn is Globals.local_connection, (
            "Function must be called locally not over '{conn}'.".format(
                conn=curmir_rp.conn
            )
        )
        pid = extract_pid(curmir_rp)
        # FIXME differentiate between don't know and know and handle err.errno == errno.EPERM:
        # EPERM clearly means there's a process to deny access to with OSError
        if pid is not None and pid_running(pid):
            log.Log.FatalError(
                """It appears that a previous rdiff-backup session with process
id %d is still running.  If two different rdiff-backup processes write
the same repository simultaneously, data corruption will probably
result.  To proceed with regress anyway, rerun rdiff-backup with the
--force option."""
                % (pid,)
            )