4 ms·
> I take it you've never used an application that hot-reloads plugins? Used and implemented many times. Sometimes this could be a problem, but IME most plugin
by wahern 3y ago
> I take it you've never used an application that hot-reloads plugins?
Used and implemented many times. Sometimes this could be a problem, but IME most plugin architectures I've seen don't rely on static constructors or destructors for implicit registration/deregistration of callbacks. Among other reasons, it's a landmine of multi-threading issues and glibc itself has historically had many bugs related to this, albeit mostly a consequence of glibc implementing (until recently) libpthread separate from libc.
Also, POSIX does not guarantee that dlclose does anything: "An application writer may use dlclose() to make a statement of intent on the part of the process, but this statement does not create any requirement upon the implementation."
> Who cares about memory leaks, right?
I can't find the blog post now, but IIRC Solaris made getenv thread-safe by never deallocating any memory allocated for the environ array or its contents. The blog post had a curious and memorable defense which explained how the memory usage was asymptotically bounded, similar to how hash table operations are described as asymptotically O(1) in time. And Solaris cares very much about memory management--unlike Linux or FreeBSD it implements strict memory accounting, so no OOM killer non-sense.
Is it ideal? No. But these are legitimate decisions taken in light of lots of experience, and if you want to write truly robust applications one has to pay attention to standards, implementation details, and best practices. IME best practice wrt module systems on Unix and the open source world generally has always been to avoid implicit registration/deregistration of callbacks. I believe the same is true in the Windows world, though I've never written much software for Windows. (Anyone know if FreeLibrary immediately invokes static destructors?)
FWIW, I have implemented hacks which relied on static constructors and where hot reloading was more problematic in the absence of static destructors. For example, I once implemented a proof of concept for automatic runtime reloading of SSL certificates and keys in the Splunk server by writing a library interposer (supporting FreeBSD, Linux, macOS, and Solaris) that installed global OpenSSL SSL_CTX callbacks. So I know why these things could be useful. But that example was a PoC hack. And even in situations where dlcose is supported as one might naively expect, you can still easily run into similar gotchas, like a user loading a module twice under different names. You have to choose either to deal with it the hard way, or disclaim support for such niche cases.