Skip to content

Instantly share code, notes, and snippets.

@L3viathan
Last active May 2, 2024 11:49
Show Gist options
  • Select an option

  • Save L3viathan/1c6f5e4402d0a591db739b7b6ec92e63 to your computer and use it in GitHub Desktop.

Select an option

Save L3viathan/1c6f5e4402d0a591db739b7b6ec92e63 to your computer and use it in GitHub Desktop.
Go backwards in time when something went wrong
import os
import sys
import inspect
import signal
from contextlib import contextmanager
def _kill_self(signum, frame):
os._exit(0)
@contextmanager
def atomic():
ppid = os.getpid()
cpid = os.fork()
if cpid:
signal.signal(signal.SIGUSR1, _kill_self)
os.waitpid(cpid, 0)
signal.signal(signal.SIGUSR1, signal.SIG_DFL) # ignore signal again
sys.settrace(lambda *a, **k:None)
frame = inspect.currentframe().f_back.f_back
def raiser(*a): raise RuntimeError
frame.f_trace = raiser
try:
yield
except RuntimeError:
return
try:
yield
except Exception:
# rollback: we exit
os._exit(0)
else:
# all good: tell state-preserved parent to kill itself
os.kill(ppid, signal.SIGUSR1)
x = 23
with atomic():
x += 1
1/0
print(x)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment