prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  `atexit.register` does not work
  ### What I did
  ```python3
  from pwn import *
  atexit.register(print, "hello world")
  exit()
  ```
  ### What I expected to see
  ```python3 test.py
  hello world
  ```
  ### What I saw
  Nothing
  
  I noticed this because `asm()`, which adds an `atexit` handler to remove the `/tmp/pwn-asm-XXXXXX` folder, does not in fact remove it, meaning multiple script runs leads to many similar folders.
  
  </issue>
  <code>
  [start of pwnlib/atexit.py]
  1 """
  2 Replacement for the Python standard library's atexit.py.
  3 
  4 Whereas the standard :mod:`atexit` module only defines :func:`atexit.register`,
  5 this replacement module also defines :func:`unregister`.
  6 
  7 This module also fixes a the issue that exceptions raised by an exit handler is
  8 printed twice when the standard :mod:`atexit` is used.
  9 """
  10 from __future__ import absolute_import
  11 from __future__ import division
  12 
  13 import sys
  14 import threading
  15 import traceback
  16 
  17 from pwnlib.context import context
  18 
  19 __all__ = ['register', 'unregister']
  20 
  21 _lock = threading.Lock()
  22 _ident = 0
  23 _handlers = {}
  24 
  25 def register(func, *args, **kwargs):
  26     """register(func, *args, **kwargs)
  27 
  28     Registers a function to be called on program termination.  The function will
  29     be called with positional arguments `args` and keyword arguments `kwargs`,
  30     i.e. ``func(*args, **kwargs)``.  The current `context` is recorded and will
  31     be the one used when the handler is run.
  32 
  33     E.g. to suppress logging output from an exit-handler one could write::
  34 
  35       with context.local(log_level = 'error'):
  36         atexit.register(handler)
  37 
  38     An identifier is returned which can be used to unregister the exit-handler.
  39 
  40     This function can be used as a decorator::
  41 
  42       @atexit.register
  43       def handler():
  44         ...
  45 
  46     Notice however that this will bind ``handler`` to the identifier and not the
  47     actual exit-handler.  The exit-handler can then be unregistered with::
  48 
  49       atexit.unregister(handler)
  50 
  51     This function is thread safe.
  52 
  53     """
  54     global _ident
  55     with _lock:
  56         ident = _ident
  57         _ident += 1
  58     _handlers[ident] = (func, args, kwargs, vars(context))
  59     return ident
  60 
  61 def unregister(ident):
  62     """unregister(ident)
  63 
  64     Remove the exit-handler identified by `ident` from the list of registered
  65     handlers.  If `ident` isn't registered this is a no-op.
  66     """
  67     if ident in _handlers:
  68         del _handlers[ident]
  69 
  70 def _run_handlers():
  71     """_run_handlers()
  72 
  73     Run registered exit-handlers.  They run in the reverse order of which they
  74     were registered.
  75 
  76     If a handler raises an exception, it will be printed but nothing else
  77     happens, i.e. other handlers will be run and `sys.excepthook` will not be
  78     called for that reason.
  79     """
  80     context.clear()
  81     for _ident, (func, args, kwargs, ctx) in \
  82         sorted(_handlers.items(), reverse = True):
  83         try:
  84             with context.local(**ctx):
  85                 func(*args, **kwargs)
  86         except SystemExit:
  87             pass
  88         except Exception:
  89             # extract the current exception and rewind the traceback to where it
  90             # originated
  91             typ, val, tb = sys.exc_info()
  92             traceback.print_exception(typ, val, tb.tb_next)
  93 
  94 # if there's already an exitfunc registered be sure to run that too
  95 if hasattr(sys, "exitfunc"):
  96     register(sys.exitfunc)
  97 
  98 sys.exitfunc = _run_handlers
  99
  [end of pwnlib/atexit.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/pwnlib/atexit.py b/pwnlib/atexit.py
  --- a/pwnlib/atexit.py
  +++ b/pwnlib/atexit.py
  @@ -13,6 +13,7 @@
   import sys
   import threading
   import traceback
  +import atexit as std_atexit
   
   from pwnlib.context import context
   
  @@ -95,4 +96,8 @@
   if hasattr(sys, "exitfunc"):
       register(sys.exitfunc)
   
  -sys.exitfunc = _run_handlers
  +if sys.version_info[0] < 3:
  +    sys.exitfunc = _run_handlers
  +else:
  +    std_atexit.register(_run_handlers)
  +
  
verification_info: {"golden_diff": "diff --git a/pwnlib/atexit.py b/pwnlib/atexit.py\n--- a/pwnlib/atexit.py\n+++ b/pwnlib/atexit.py\n@@ -13,6 +13,7 @@\n import sys\n import threading\n import traceback\n+import atexit as std_atexit\n \n from pwnlib.context import context\n \n@@ -95,4 +96,8 @@\n if hasattr(sys, \"exitfunc\"):\n     register(sys.exitfunc)\n \n-sys.exitfunc = _run_handlers\n+if sys.version_info[0] < 3:\n+    sys.exitfunc = _run_handlers\n+else:\n+    std_atexit.register(_run_handlers)\n+\n", "issue": "`atexit.register` does not work\n### What I did\r\n```python3\r\nfrom pwn import *\r\natexit.register(print, \"hello world\")\r\nexit()\r\n```\r\n### What I expected to see\r\n```python3 test.py\r\nhello world\r\n```\r\n### What I saw\r\nNothing\r\n\r\nI noticed this because `asm()`, which adds an `atexit` handler to remove the `/tmp/pwn-asm-XXXXXX` folder, does not in fact remove it, meaning multiple script runs leads to many similar folders.\n", "before_files": [{"content": "\"\"\"\nReplacement for the Python standard library's atexit.py.\n\nWhereas the standard :mod:`atexit` module only defines :func:`atexit.register`,\nthis replacement module also defines :func:`unregister`.\n\nThis module also fixes a the issue that exceptions raised by an exit handler is\nprinted twice when the standard :mod:`atexit` is used.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\n\nimport sys\nimport threading\nimport traceback\n\nfrom pwnlib.context import context\n\n__all__ = ['register', 'unregister']\n\n_lock = threading.Lock()\n_ident = 0\n_handlers = {}\n\ndef register(func, *args, **kwargs):\n    \"\"\"register(func, *args, **kwargs)\n\n    Registers a function to be called on program termination.  The function will\n    be called with positional arguments `args` and keyword arguments `kwargs`,\n    i.e. ``func(*args, **kwargs)``.  The current `context` is recorded and will\n    be the one used when the handler is run.\n\n    E.g. to suppress logging output from an exit-handler one could write::\n\n      with context.local(log_level = 'error'):\n        atexit.register(handler)\n\n    An identifier is returned which can be used to unregister the exit-handler.\n\n    This function can be used as a decorator::\n\n      @atexit.register\n      def handler():\n        ...\n\n    Notice however that this will bind ``handler`` to the identifier and not the\n    actual exit-handler.  The exit-handler can then be unregistered with::\n\n      atexit.unregister(handler)\n\n    This function is thread safe.\n\n    \"\"\"\n    global _ident\n    with _lock:\n        ident = _ident\n        _ident += 1\n    _handlers[ident] = (func, args, kwargs, vars(context))\n    return ident\n\ndef unregister(ident):\n    \"\"\"unregister(ident)\n\n    Remove the exit-handler identified by `ident` from the list of registered\n    handlers.  If `ident` isn't registered this is a no-op.\n    \"\"\"\n    if ident in _handlers:\n        del _handlers[ident]\n\ndef _run_handlers():\n    \"\"\"_run_handlers()\n\n    Run registered exit-handlers.  They run in the reverse order of which they\n    were registered.\n\n    If a handler raises an exception, it will be printed but nothing else\n    happens, i.e. other handlers will be run and `sys.excepthook` will not be\n    called for that reason.\n    \"\"\"\n    context.clear()\n    for _ident, (func, args, kwargs, ctx) in \\\n        sorted(_handlers.items(), reverse = True):\n        try:\n            with context.local(**ctx):\n                func(*args, **kwargs)\n        except SystemExit:\n            pass\n        except Exception:\n            # extract the current exception and rewind the traceback to where it\n            # originated\n            typ, val, tb = sys.exc_info()\n            traceback.print_exception(typ, val, tb.tb_next)\n\n# if there's already an exitfunc registered be sure to run that too\nif hasattr(sys, \"exitfunc\"):\n    register(sys.exitfunc)\n\nsys.exitfunc = _run_handlers\n", "path": "pwnlib/atexit.py"}]}