5.3 Bugs

There are several design decisions you may stumble across when using pam_python. One is that the Python PAM module is isolated from the rest of the Python environment. This differs from a import'ed Python module, where regardless of how many times a module is imported there is only one copy that shares the one global name space. So, for example, if you import your Python PAM module and then debug it as suggested above then there will be 2 copies of your Python PAM module in memory - the imported one and the one PAM is using. If the PAM module sets a global variable you won't see it in the import'ed one. Indeed, obtaining any sort of handle to the module the PAM is using is near impossible. This means the debugger can inspect variables in the module only when a breakpoint has one of the modules functions in its backtrace.

There are a few of reasons for this. Firstly, the PAM Module Writers Guide says this is the way it should be, so pam_python encourages it. Secondly, if a PAM application is using a Python PAM Module its important the PAM module remains as near to invisible as possible to avoid conflicts. Finally, and most importantly, references to objects constructed by the Python PAM module must never leak. This is because the destructors to those objects are C functions that live in pam_python, and those destructors are called when all references to the objects are gone. When pam_end(3) is called pam_python is unloaded, and with it goes the destructor code. Should a reference to an object defined by pam_python exist after pam_end(3) returns the call to destructor will result in a jump to a non-existent address causing a SIGSEGV.

Another potential trap is the initialisation and finalisation of the Python interpreter itself. Calling the interpreter's finalisation routine while it is in use would I imagine be a big no-no. If pam_python has to initialise the interpreter (by calling Py_Initialize()) then it will call its finaliser (Py_Finalize() when the last Python PAM module is destroyed. This is heuristic works in most scenarios. One example where is won't work is a sequence like: start-python-pam-module; application-initialises-interpreter; stop-python-pam-module; application-stops-interpreter. This is doomed to fail.