Golang Package: plugin
tip.golang.org
tip.golang.org
> The inability to unload a plugin defeats the use I would have for this, unfortunately. A long running service with plugins may want to load new, updated versions of an existing plugin. Not being able to unload the old version, ends up creating stale references which will keep piling up for the lifetime of the process. As I understand it, this is essentially a memory leak. [...]
> https://www.reddit.com/r/golang/comments/53adu8/a/d7rmmco
There is also this project by Hashicorp: https://github.com/hashicorp/go-plugin
Disagree with the problem of unloading plugins. From the sizes of Go binaries and memory sizes, one could easily load 10k+ plugins before the process needed a restart. Would be nice to have GC, but having plugins is such an increased benefit. To me this sounds like, Git is crap because you can't unload stored objects.
https://github.com/RedisLabs/rgm/blob/master/example/module....
Why not?
Module loading is something that can be added to a language later, but I suspect safe module unloading is something that has to go in from day one to ever work right. Even in languages that support it (Erlang) it's got a tricky list of caveats to keep track of that strike me as fairly essential to the problem, rather than accidental (in the Fred Brooks sense of the terms).
Hence why Java and .NET restrict it to Class Loaders/AppDomains.
- no thread is running code in the plugin.
- no thread has a return address on the stack somewhere in the plugin.
- no variable stores a pointer pointing into the plugin (This includes objects whose destructor is implemented in the plugin)
- no signal handler points into the plugin.
- no kernel thread is reading the plug-ins memory.
In addition there are race conditions to take care of (e.g. thread T unloads a plugin that thread U is loading)
With a 64 bit address space, I guess you can get around most if not all problems by mapping the memory that was mapped to the plugin as "can't read, can't write, can't execute", so that you crash hard if somebody tries to access it, but if you do that, you can just as well keep the code around.
Go is garbage-collected, so it likely already has a lot of the logic to do this, but even then, combining the functionality to get a robust implementation of plugin unloading is a lot of work.
Consider another instance where file names are automatically mangled: GCC linking with libraries with the switch -lfoo. That has honestly caused me no end of problems. It would have been better if they required an explicit -llibfoo.so from the start.
Go already has several easy methods for OS-specific code if you want.
For extra runtime speed you could build OS specific versions of that function using build flags, so for each target OS it has one implementation and you have no switch/case or anything in runtime.
" 5 // +build linux,cgo"
The Windows version isn't there yet - it could encapsulate that logic.
I would go so far as to say an absolute path should be required.
What's next? Generics?
This is not like dynamic linking hell you can get yourself into when writing C.
In my Go code, I've just used subprocesses for that. Stdin & stdout, plus a simple serialisation format, and I'm done.
Not suitable for high performance stuff, of course, but good enough for my needs.
So basically something like apache modules - either you can load the module or not - vs something like "cannot find symbol foo in foo.so.0.1."
No, but they will eventually need to handle plugin versions.
Because that doesn't sound very reasonable to me, even after ignoring that plugins aren't really dependencies anyway.