Date: Tue, 13 Aug 2002 11:14:32 +0300 From: Maxim Sobolev <sobomax@FreeBSD.org> To: Terry Lambert <tlambert2@mindspring.com> Cc: hackers@FreeBSD.ORG, audit@FreeBSD.ORG, Alexander Litvin <archer@whichever.org>, Andriy Gapon <agapon@excite.com> Subject: Re: Thread-safe resolver [patches for review] Message-ID: <3D58BFE8.9281433@FreeBSD.org> References: <3D578A99.F0821712@FreeBSD.org> <3D5792CD.497C80F0@mindspring.com> <3D57A9D4.DAA043EF@FreeBSD.org> <3D57CF6D.2982CE8@mindspring.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Terry Lambert wrote: > > Maxim Sobolev wrote: > > > You may also want to consider the use of a .init and .fini > > > section for the code, to permit the creation of an initial > > > lookup context chunk; this is kind of a tradeoff, but it will > > > mean that a server will not have to do the recheck each time. > > > The .fini section would aloow auto-cleanup. This may be a > > > necessity for a long running program that uses a shared object > > > to perform the thread creation and lookup (you could leak > > > memory, otherwise). > > > > Could you please elaborate how exactly memory could be leaked in this > > case, if the program does correctly shut down all its threads? > > Create PIC object foo.so. > Link PIC object foo.so against libc.so. > Call dlopen to load module foo.so into program "bob". > Call function in foo.so from program "bob". > Function in foo.so creates two threads, one for IPv4 lookup, > another for IPv6 lookup to cause lookups to proceed > concurrently. > Lookup completes. > Unload module foo.so. > -> leak memory in libc.so image This scenario doesn't look as a legitimate way to do things for me. Let's inspect what will happen when you are unloading a PIC module, which has one or more threads running. There are two possibilities: either thread scheduler (libc_r) was linked with the program itself and therefore loaded with it, or it was linked with PIC module and loaded along with that module. In the first case, after you have dlclose'd the PIC module, dynamic linker will unmap module's code from memory, but the thread scheduler will remain running and on the next attempt to pass control to the thread in your PIC module will probably get SIGBUS due to the fact that code is no longer mapped. In the second case, you'll unload module along with thread scheduler, but thread-scheduling signals setup will remain in place, so that shortly you will get the same SIGBUS, when the kernel will be trying to delivery signal to no longer mapper region. In either case, you will get the problem much more serious than memory leak. > The assumption (which is potentially wrong) is that the program > will correctly shut down all its threads, when in fact it was a > module not under the programs control that created and used the > threads. I do not quite agree. In such case, the module should probably have destructor function, either placed into the fini section, or to be explicitly called by the program before dlclose(). > The leak depends on: > > 1) A pool of worker threads being created and left around > or the purpose of simultaneous resolution > > 2) The parent shutting down the module without explicitly > dealing with the threads (basically, code which would > need to live in ".fini" of the foo.so, and could not be > automatically triggered on unload of foo.so any other way). > > I think that parallel IPv6/IPv4 resolution presented as a single > serial interface is a high probability implementation with the > support for threaded access to the resolver, particularly with > the Mozilla code acting the way it does. > > > I also would like to hear from you whether or not you think that we > > need all those gethostbyXXX_r(3) functions. > > No. I don't think any of the _r functions are needed, so long > as the results are not cached by pointer instead of a copy, > before passing them from one thread to another. It's a risk on > the clobber case of a call with a cached reference outstanding > but not processed by another thread which is not an issue with > the _r functions, which require that you pass the storage down. > > Of course, if you pass down per thread storage, you could have > the same problem if you didn't copy rather than reference the > results before passing to another thread by address. > > Given that, per thread allocations ("thread local storage") > makes more sense than allocate/free fights between threads > based on who's responsible for owning the memory after an > inter-thread call. 8-). Thank you for the explanation! -Maxim To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3D58BFE8.9281433>