![]() |
|
Message-ID: <aDcfxEXp-r2bRCaJ@voyager> Date: Wed, 28 May 2025 16:37:56 +0200 From: Markus Wichmann <nullplan@....net> To: musl@...ts.openwall.com Subject: Re: Deadlock in dynamic linker? Am Tue, May 27, 2025 at 07:14:15PM +0200 schrieb Thorsten Glaser: > On Tue, 27 May 2025, Markus Wichmann wrote: > > >But __libc_exit_fini() refuses to destroy libraries that haven't been > >constructed completely. If p->constructed is zero, a node is skipped > > Isn’t that the *good* thing? > Sometimes the things I say actually are in relation to the things I quote. In this case, I suggested to put nodes in the list only when construction has finished, then Rich said this can't be done, among other reasons because it may cause __libc_exit_fini() to miss partially constructed libraries, and then I remarked, that partially constructed libraries are skipped anyway. I wasn't arguing against skipping them, merely that the concern was invalid. But I think I get it now. By putting the node on the list early, we ensure that __libc_exit_fini() waits for the library to be completely constructed as soon as the first constructor is run. Unless exit() is called from such a constructor (which can be recursively called from a constructor inside a dlopen()ed library). > >By adding nodes to the fini list only when construction has finished, we > >would also get rid of the need to have __libc_exit_fini() wait for > >construction to finish first. > > AIUI that may change the order which is inacceptable? The exact order of nodes on the list is unimportant. What is important is that dependencies not appear on it in front of their dependents. And because that is the exact opposite of the order the constructor calls must be in, we currently just push nodes to the list in LIFO fashion to invert the order. Thing is, I am not at all sure this leads to the correct order. In the scenario I made up, if we leave the concurrent exit call aside, liba is opening libb dynamically in the constructor. It would not be surprising to see liba actually use that library handle to do things such as call functions from libb, and I don't see why they shouldn't. Possibly even a liba destructor could do such a thing. But the current behavior will have libb on the fini list in front of liba, causing liba to call libb functions after the latter has been destroyed. I don't really know how to remedy this, and nor whether it is a common scenario out in the world. Nor do I know how to look up if any spec actually limits what destructors can do. The gABI I have seen does allow the implementation to place arbitrary limits on pre-init functions, but says nothing about initializers or finalizers in that regard. Ciao, Markus
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.