diff options
author | Armin Rigo <arigo@tunes.org> | 2018-02-27 21:18:33 +0100 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2018-02-27 21:18:33 +0100 |
commit | a4c04234554d1791ff904539078d6f7826434970 (patch) | |
tree | ccf06aeba430b30581e7fa4a90fbe273aeec37e2 | |
parent | df3534a0953119d149d7b8cd3665d2e9859d7c2a (diff) | |
download | cffi-a4c04234554d1791ff904539078d6f7826434970.tar.gz |
Ignore multiple dlclose(), like file.close() does in Python
-rw-r--r-- | c/_cffi_backend.c | 9 | ||||
-rw-r--r-- | c/cdlopen.c | 23 | ||||
-rw-r--r-- | c/test_c.py | 1 | ||||
-rw-r--r-- | testing/cffi0/test_function.py | 4 | ||||
-rw-r--r-- | testing/cffi1/test_re_python.py | 4 |
5 files changed, 17 insertions, 24 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c index 7106c65..7f44d12 100644 --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -4099,10 +4099,11 @@ static PyObject *dl_write_variable(DynLibObject *dlobj, PyObject *args) static PyObject *dl_close_lib(DynLibObject *dlobj, PyObject *no_args) { - if (dl_check_closed(dlobj) < 0) - return NULL; - dlclose(dlobj->dl_handle); - dlobj->dl_handle = NULL; + if (dlobj->dl_handle != NULL) + { + dlclose(dlobj->dl_handle); + dlobj->dl_handle = NULL; + } Py_INCREF(Py_None); return Py_None; } diff --git a/c/cdlopen.c b/c/cdlopen.c index 361b0d1..46ce153 100644 --- a/c/cdlopen.c +++ b/c/cdlopen.c @@ -62,22 +62,17 @@ static PyObject *ffi_dlclose(PyObject *self, PyObject *args) return NULL; libhandle = lib->l_libhandle; - lib->l_libhandle = NULL; - - if (libhandle == NULL) { - PyErr_Format(FFIError, "library '%s' is already closed " - "or was not created with ffi.dlopen()", - PyText_AS_UTF8(lib->l_libname)); - return NULL; - } - - /* Clear the dict to force further accesses to do cdlopen_fetch() - again, and fail because the library was closed. */ - PyDict_Clear(lib->l_dict); + if (libhandle != NULL) + { + lib->l_libhandle = NULL; - if (cdlopen_close(lib->l_libname, libhandle) < 0) - return NULL; + /* Clear the dict to force further accesses to do cdlopen_fetch() + again, and fail because the library was closed. */ + PyDict_Clear(lib->l_dict); + if (cdlopen_close(lib->l_libname, libhandle) < 0) + return NULL; + } Py_INCREF(Py_None); return Py_None; } diff --git a/c/test_c.py b/c/test_c.py index 4ff1549..caecbec 100644 --- a/c/test_c.py +++ b/c/test_c.py @@ -409,6 +409,7 @@ def test_load_standard_library(): # x.close_lib() py.test.raises(ValueError, x.load_function, BVoidP, 'sqrt') + x.close_lib() def test_no_len_on_nonarray(): p = new_primitive_type("int") diff --git a/testing/cffi0/test_function.py b/testing/cffi0/test_function.py index 077f806..6af8aa6 100644 --- a/testing/cffi0/test_function.py +++ b/testing/cffi0/test_function.py @@ -507,9 +507,6 @@ class TestFunction(object): ffi.cdef("int foobar(void); int foobaz;") lib = ffi.dlopen(lib_m) ffi.dlclose(lib) - e = py.test.raises(ValueError, ffi.dlclose, lib) - assert str(e.value).startswith("library '") - assert str(e.value).endswith("' has already been closed") e = py.test.raises(ValueError, getattr, lib, 'foobar') assert str(e.value).startswith("library '") assert str(e.value).endswith("' has already been closed") @@ -519,3 +516,4 @@ class TestFunction(object): e = py.test.raises(ValueError, setattr, lib, 'foobaz', 42) assert str(e.value).startswith("library '") assert str(e.value).endswith("' has already been closed") + ffi.dlclose(lib) # does not raise diff --git a/testing/cffi1/test_re_python.py b/testing/cffi1/test_re_python.py index 815c435..65c2882 100644 --- a/testing/cffi1/test_re_python.py +++ b/testing/cffi1/test_re_python.py @@ -119,12 +119,10 @@ def test_dlclose(): str_extmod = extmod.encode('utf-8') else: str_extmod = extmod - e = py.test.raises(ffi.error, ffi.dlclose, lib) - assert str(e.value).startswith( - "library '%s' is already closed" % (str_extmod,)) e = py.test.raises(ffi.error, getattr, lib, 'add42') assert str(e.value) == ( "library '%s' has been closed" % (str_extmod,)) + ffi.dlclose(lib) # does not raise def test_constant_via_lib(): from re_python_pysrc import ffi |