S1gma did report that doing separate plugin processing on Linux makes u-he menus not working. The menu appear but the result returned from the menu is not caught by the plugin.
So when a menu is popped, the plugin forks, execute a dialog binary which shows the menu and write the selected entry id to the standard output (which has been pipe(), dup2()) and gets read by the plugin.
No, we don’t replace fork() or related functions.
Wonder why you need to fork here at all. Forks are pretty evil and a “heavy thing to do” in big apps like Renoise. So if they can be avoided, they should be avoided.
Because qt and gtk uses singletons, and can’t be initialized multiple times etc… And nothing guarantee that it is safe to use them in a plugin. Tell me if I’m wrong there and it will be my pleasure to get those menu and dialog into the plugin.
I dislike the idea of forking as well. But it is the shortest path I found to get the menu and dialogs working for me.
IC. Using the u-he internal UIs (or Juce or whatever else they base on) maybe would make more sense then. Still have no idea why the fork/pipe does not work in the plugin server.
You can attach gdb to the “RenoisePluginServer” executable after the plugin gets loaded. Maybe this gives you a few more hints of what exactly goes wrong here.
The error is that when I waitpid(…) my child is already gone. So I wonder if renoise does some garbage collection here? I mean do you call: pid_t wait(int *); ?
If this is the case, you can use waitpid() instead?
The error is that when I waitpid(…) my child is already gone. So I wonder if renoise does some garbage collection here? I mean do you call: pid_t wait(int *); ?
If this is the case, you can use waitpid() instead?
Thanks.
Hello.
No, but we’re trying to automatically reap zombies by installing a SIG_IGN handler for SIGCHLD before forking, and are also setting the SA_NOCLDWAIT flag. So I wonder where that zombie from the screenshot above comes from. If I understand all this correctly, this will then then reap your forked process too, assuming that the forked process inherits signal settings from the parent process.
Here’s what exactly we do before forking the plugin server process:
From my understanding of sigaction, we can’t achieve a race free and robust design with it in our context.
Yes. My idea was to disable the SA_NOCLDWAIT flag from the signal handler before you’re doing !your! fork, then restoring the flags it after the waitpid. Sorry for not being clear here.
This way you should always be able to wait or waitpid for your forked child process, even when something else (the host - some library - other plugins) have fumbled around with the signal handler settings.
You may in your signal handler just use waitpid()?
We’re neither using waitpid nor wait in this context.
True, but this will only be a problem when you’re forking multiple times within your own menu handlers or on multiple threads. In other words: this is up to you to handle, to deal with.
I’ll give the “waitpid” thing within the signal handler a try, but strongly suggest that you avoid relying on wait[pid] completely, and use pipes or some other forms of inter process communication instead.
Ideally you should avoid the fork completely here: forking is plain evil and overkill in this case. Also some libraries or other plugins may break/change signal handling too, so this quite likely will break sooner or later again even if we fix this now within Renoise.
Avoid forks => true, but it requires to implements the menu myself and all the dialogs and widgets, some work is going in that direction but it will not be ready tomorrow. And the fork is not happening 48000 times per second, so I bet that no one is able to measure its overhead.
Thank you for giving waitpid a try!
I use pipe for the inter-process thing. When I create a process, I do waitpid() for it, it seems to be the natural thing to do.