Skip to content

Instantly share code, notes, and snippets.

@XeCycle
Last active March 10, 2021 07:06
Show Gist options
  • Save XeCycle/ca08714f48bcb4bd0c2524d0bd64ecdc to your computer and use it in GitHub Desktop.
Save XeCycle/ca08714f48bcb4bd0c2524d0bd64ecdc to your computer and use it in GitHub Desktop.
cpython signal handlers while creating C resources?
$ python test_cffi_sig.py
resources created
Traceback (most recent call last):
File "/.../test_cffi_sig.py", line 41, in <module>
x = using_outp()
File "/.../test_cffi_sig.py", line 35, in using_outp
lib.my_create_resource_outp(out)
KeyboardInterrupt
release 42
#include <stdio.h>
#include <signal.h>
int my_create_resource()
{
raise(SIGINT);
printf("resources created\n");
return 42;
}
void my_create_resource_outp(int* out)
{
raise(SIGINT);
printf("resources created\n");
*out = 42;
}
void my_release_resource(int fd)
{
printf("release %d\n", fd);
}
from cffi import FFI
ffi = FFI()
ffi.cdef("""\
int my_create_resource();
void my_create_resource_outp(int* out);
void my_release_resource(int fd);
""")
lib = ffi.dlopen("./test_cffi_sig.so")
# x = ffi.gc(lib.my_create_resource(), lib.my_release_resource) # leaks
# also leaks
def run():
res = None
try:
res = lib.my_create_resource()
finally:
if res is not None:
res = ffi.gc(res, lib.my_release_resource)
class Res:
def __init__(self, fd) -> None:
self.fd = fd
def __del__(self):
lib.my_release_resource(self.fd)
# this one doesn't leak
def using_outp():
out = ffi.new("int[1]")
out[0] = -1
res = None
try:
lib.my_create_resource_outp(out)
finally:
if out[0] >= 0:
res = Res(out[0])
return res
x = using_outp()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment