Last active
March 10, 2021 07:06
-
-
Save XeCycle/ca08714f48bcb4bd0c2524d0bd64ecdc to your computer and use it in GitHub Desktop.
cpython signal handlers while creating C resources?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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