News for hackers. Stuff that matters.
Re:C++ Exit-Time Destructors by o11c on Saturday March 23, 2024 @01:21AM (#39797675)
Side note: dynamic library unloading (and, for that manner, multiple loading of the same library; see `dlmopen`) is finicky because the language has no concept of ownership of things like function pointers and pointers to static data. It's easy to imagine a better language, though this would of course require a lot of low-level implementation work!
Re:C++ Exit-Time Destructors by dataflow on Saturday March 23, 2024 @01:30AM (#39797713)
> the language has no concept of ownership of things like function pointers and pointers to static data. It's easy to imagine a better language

I actually have both a hard time imagining a better language (not saying it's impossible, just that it's not trivial for me to see) and also how ownership would resolve this issue. Could you elaborate?

Re:C++ Exit-Time Destructors by lldb on Saturday March 23, 2024 @02:42AM (#39797945)
I tested this recently and it definitely works as expected in c++ - destructors of static lifetime variables are called when the library is unloaded.
Re:C++ Exit-Time Destructors by rwmj on Saturday March 23, 2024 @03:39AM (#39798185)
Only in trivial cases. The problem is when another part of the program holds a function pointer into the library which has been unloaded. This can happen in particular when you combine libraries and threads:

libvirt has long been linked with -Wl,-z -Wl,nodelete to avoid this:

https://gitlab.com/libvirt/libvirt/-/commit/8e44e5593eb9b89f...

Another case in libnbd which really demonstrates how hard this is:

https://gitlab.com/nbdkit/libnbd/-/commit/368e3d0d5a8871aad5...

Re:C++ Exit-Time Destructors by alexey-salmin on Saturday March 23, 2024 @05:11AM (#39798526)
> The problem is when another part of the program holds a function pointer into the library which has been unloaded.

How is this different from holding a pointer to an object being deleted?

Re:C++ Exit-Time Destructors by rwmj on Saturday March 23, 2024 @05:40AM (#39798636)
That it's very hard to avoid (we think in fact impossible), because of the way that Linux _exit(2) works when you have threads, destructors and thread-local storage together. This is even if you are very careful. You should probably read the links I posted.
Re:C++ Exit-Time Destructors by alexey-salmin on Saturday March 23, 2024 @06:10AM (#39798744)
I did and this looks like a library design issue, which is now impossible to solve without breaking the ABI. I argue though that a design that doesn't suffer from this issue exists because there is a way to serialize all these operations in a safe way.
Re:C++ Exit-Time Destructors by rwmj on Saturday March 23, 2024 @07:53AM (#39799242)
Thread-local storage + destructors is, as far as we can tell, impossible to use safely by any significantly complicated program or library. It's largely because of how Linux shoots down programs on exit by killing the threads in any order without notice. It could be fixed in Linux, although I can also understand why Linux developers wouldn't want to do that as it would push significant complexity there.
Re:C++ Exit-Time Destructors by jenadine on Saturday March 23, 2024 @05:42AM (#39798645)
It's not much different. But programmers tend to assume that static data lives forever and don't always think of this problem.
Re:C++ Exit-Time Destructors by pjmlp on Saturday March 23, 2024 @06:21AM (#39798797)
Which is why that kind of stuff only works properly with languages that combine dynamic loading with rich runtimes, alongside automatic memory management, having all puzzle pieces to work together to keep the application running when the library is removed again.

I came to accept that in languages like C and C++, the best path for dynamic loading code is really via OS IPC and external processes, the decrease in hardware resources and simpler programming model of using shared libraries as plugins, isn't worth the endless amount of debugging hours regarding program crashes.