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

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.

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-).

-- Terry

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to