Linux: Menus don't work in bridged U-he VST plugins

Hi,

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.

Thanks for having a look!

Hello. Not sure how we could help here to avoid/fix this?

I was wondering if renoise does anything special like replace some standard functions (like carla replaces fork())?

I wonder why the u-he plugins behave differently when they’re isolated.

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.

Thanks taktik, I had no time to debug it yesterday, I hope that I’ll be able to tonight.

Cheers :slight_smile:

Hi Taktik,

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.

By the way it seems that you have a zombie child:

Hello,

I noticed the bug too : U-He menus do not work when plugins are run in a sandbox. Everything is fine when this option is not checked.

Taktik, did you manage to reproduce the bug ?

Hi Taktik,

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:

sigaction(SIGCHLD, NULL, &sa);
sa.sa_handler = SIG_IGN;
sa.sa_flags |= SA_NOCLDWAIT;
sigaction(SIGCHLD, &sa, NULL);

This would also mean that launching any bridged plugin in Renise will break u-he menues - event when the u-he plugin is not bridged.

You could work around this by installing your own sig handler before forking, then restoring it when you’re done?

From my understanding of sigaction, we can’t achieve a race free and robust design with it in our context.

The menus are working fine when we do not use the bridging.

By the way, there are also the wine bridges which forks. (vst-bridge and airwaves).

– edit

You may in your signal handler just use waitpid()?

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.

Sorry but I see races with your solution:

We start with the CTX0 for the sigaction.

Lib1 fork(), saves CTX0, and pushes CTX1

Lib2 fork(), saves CTX1, and pushes CTX2

Lib1 waitpid(), then restores CTX0 ==> will lib2 be able to waitpid after that?

Lib2 waitpid(), then restores CTX1 ==> CTX0 is not restored and should be restored here.

Why saving the pid of your child and use your event SIGCHLD to check your childs with waitpid(pid, WNOHANG); is a problem?

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.

The next plugins release will include a workaround for this issue :yeah:

The next plugins release will include a workaround for this issue :yeah:

Great. Also added a workaround for this here, but we’ll then add/include this in the next bigger Renoise update instead of releasing a bugfix update.

Double great then :clownstep:

Fix available at:http://www.kvraudio.com/forum/viewtopic.php?f=31&t=424953

BTW, Hive is also there :wink: