Rob Crittenden wrote: > I'm having an issue with mod_nss, an Apache module I wrote that provides > SSL using NSS. > > The way Apache loads modules is a tad strange.
I'd say it's more than a tad! > What it does is it loads them one time in order to get its list of > configuration directives and it verifies that the configuration is ok. It > also runs through the initialization routines. > In my case this is needed so I still have stdin/stdout and can prompt > for the PIN. Can't you use /dev/tty instead of stdin/stdout? > Once the first round of module loading is done > stdin/out/err are all closed. > > Apache then unloads the module, then reloads it again. I'm not really asking you to defend any of that, but ... do you have any idea what (if anything) is the benefit of that strategy? > I had to write a fair bit of code to handle this, in particular because NSS > needs to shut down gracefully otherwise it won't start up again once the > module gets loaded for the 2nd time. Yes, that's not uncommon. Opens need to be closed, mallocs need to be freed (as you know :). > The specific problem I'm having is with the NSS session cache. You know that NSS has (potentially) two separate session caches, the client cace (of sessions which NSS began by acting as an SSL client), and the server session cache (of sessions for which NSS acted as the server). They're managed entirely separately. > I periodically get a core dump in the LockPoller thread (sslsnce.c). In this case, it is apparent that you're discussing the server cache. The server cache can operate in either of two modes: single process or multiple process. There are separate server cache initialization functions, one for single process server caches, and another for multi-process server caches (it has the letters MP in the name). In the latter case, the server session cache is kept in shared memory, so that multiple processes can all share a single common pool of sessions. One process creates the cache in unnamed (a.k.a. "anonymous") shared memory and the other processes that share it must all inherit it as children of the process that created it. The parent process also creates a thread to watch the shared memory, to deal with the possibility that one of the children might die while holding a lock in that shared memory. On some unix/linux systems, there is a problem if the parent has multiple threads going when it forks a child. So we need to have a way to stop the lock poller thread prior to fork, and start it up again in the parent after the fork. See https://bugzilla.mozilla.org/show_bug.cgi?id=339466 > The cache is disappearing underneath the thread and bad things happen. > It's basically a race condition to see if this thread can exit before > its data disappears. The lock poller thread definitely needs to be stopped in the parent process before unloading the module. However, there is an issue here regarding inheritance. It would be wrong to create the shared memory cache in a parent process, fork the children, then shutdown the shared memory cache and create another one. So, this raises numerous questions and ideas. I'll start with one question. Q1) Is this a multi-process shared server cache installation? Do you intend to operate the shared memory session cache? If not, the easiest solution is for you to use the single proecss server session cache. > A potential fix I have is to not initialize the cache during the first > module load. Seems to me that your options might include: a) do NOTHING on the first module load, and do everything on the second module load. b) do all the work on the first module load. Don't really shut down the module after the first load (that is, pretend that you shut down). Then do nothing on the second load, and continue to use the stuff loaded the first time. c) really startup and shutdown everything all the way twice. The questions in my mind are: when (if ever) does the process doing this fork the children that will share the session cache? Is it during the first time the module is loaded? or between the first and second time? or after the second time? or is this only in the children processes? or ?? or are there perhaps no children involved? The answers to those questions would be expected to suggest how best to handle all this module loading/unloading. > I've always been under the impression that initializing the > cache is one of the things one should do in an NSS app and I don't want > to introduce other, worse side-effects. A server app should definitely initialize the server session cache before starting to accept any SSL/TLS connections. When multiple processes are all accepting connections on a shared port, they should also all share the server session cache for that port. The cache has to be initialized before the child processes are forked so that they will inherit it, because inheritance is the only way to get the shared memory cache. To complicate matters, PKCS#11 modules should NOT be loaded when a process forks. Each child process must initialize its PKCS#11 modules for itself. So, for multi-process shared-memory servers, the parent should create the server session cache and create the listen socket(s), THEN spawn the children, which will inherit the shared cache and shared listen sockets, and then finally it (and each of the children) should initialize the PKCS#11 module for itself. Or, if the parent will not also act as a server, but only the children will accept connections on sockets, the parent can skip initializating the PKCS#11 module alltogther. This means that initializing the NSS/SSL server session cache takes place BEFORE calling NSS_Init (or any of its variants). Many find this surprising. The "selfserv" demo server app does all this correctly, IINM. > Assuming that is ok, is it bad to call > SSL_ShutdownServerSessionIDCache() if the cache hasn't been initialized? No, that should be harmless, as long as you don't have multiple threads trying to do this simultaneously. Of course, it would be a programming error to try to do this in multiple threads simultaneously. > I briefly looked at the code and it seems ok to me but I don't want to > make assumptions. It is intended to be safe to close the global server cache instance even if it has not been initialized. If it should prove not to be safe, that would be an NSS bug. > thanks Hope this helps. I have a feeling I've just made the problem seem bigger :) > rob -- Nelson B _______________________________________________ dev-tech-crypto mailing list dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto