From ec3be7d441b7bc1888186c05db6e6b46abe63879 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Fri, 18 Sep 2015 01:38:53 -0400 Subject: MUTEX callbacks via ctypes. Beware of Garbage Collector. --- py11/__init__.py | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'py11') diff --git a/py11/__init__.py b/py11/__init__.py index bb4813f..86eb346 100644 --- a/py11/__init__.py +++ b/py11/__init__.py @@ -35,24 +35,31 @@ class PKCS11 (object): self.so.C_GetInfo(byref(info)) return info.cryptokiVersion - # http://stackoverflow.com/questions/15786635/using-ctypes-to-write-callbacks-that-pass-in-pointer-to-pointer-parameters-to-be - # suggests that it should be straightforward to write callback - # functions to implement the mutex semantics, and we get the - # CK_CREATEMUTEX call, but we dump core on the CK_LOCKMUTEX call. - # Specifying CKF_OS_LOCKING_OK does work, and is sufficient for most - # purposes, so leaving the callbacks out of the API for now. - - def C_Initialize(self, flags = 0): - if flags == 0: + # Be very careful if you try to provide your own locking functions. + # For most purposes, if you really just want locking, you're best + # off specifying CKF_OS_LOCKING_OK and letting the C code deal with + # it. The one case where you might want to provide your own locking + # is when writing tests to verify behavior of the locking code. + # + # We have to stash references to the callback functions passed to + # C_Initialize() to avoid dumping core when the garbage collector + # deletes the function pointer instances out from under the C code. + + def C_Initialize(self, flags = 0, create_mutex = None, destroy_mutex = None, lock_mutex = None, unlock_mutex = None): + if flags == 0 and create_mutex is None and destroy_mutex is None and lock_mutex is None and unlock_mutex is None: + self._C_Initialize_args = None self.so.C_Initialize(None) else: - init_arg = CK_C_INITIALIZE_ARGS(cast(None, CK_CREATEMUTEX), cast(None, CK_DESTROYMUTEX), - cast(None, CK_LOCKMUTEX), cast(None, CK_UNLOCKMUTEX), - flags, None) - self.so.C_Initialize(cast(byref(init_arg), CK_VOID_PTR)) + create_mutex = cast(None, CK_CREATEMUTEX) if create_mutex is None else CK_CREATEMUTEX(create_mutex) + destroy_mutex = cast(None, CK_DESTROYMUTEX) if destroy_mutex is None else CK_DESTROYMUTEX(destroy_mutex) + lock_mutex = cast(None, CK_LOCKMUTEX) if lock_mutex is None else CK_LOCKMUTEX(lock_mutex) + unlock_mutex = cast(None, CK_UNLOCKMUTEX) if unlock_mutex is None else CK_UNLOCKMUTEX(unlock_mutex) + self._C_Initialize_args = CK_C_INITIALIZE_ARGS(create_mutex, destroy_mutex, lock_mutex, unlock_mutex, flags, None) + self.so.C_Initialize(cast(byref(self._C_Initialize_args), CK_VOID_PTR)) def C_Finalize(self): self.so.C_Finalize(None) + self._C_Initialize_args = None def C_GetSlotList(self): slots = (CK_SLOT_ID * 10)() -- cgit v1.2.3