Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confirm demoplugin works in Windows/Linux #45

Open
dudk opened this issue Apr 17, 2021 · 23 comments
Open

Confirm demoplugin works in Windows/Linux #45

dudk opened this issue Apr 17, 2021 · 23 comments
Labels
help wanted plugin Issue relates to building Go plugins

Comments

@dudk
Copy link
Member

dudk commented Apr 17, 2021

It seems that the following command is enough to produce working plugin for Windows/Linux:

go build --buildmode c-shared --tags plugin

Confirmation is required.

@dudk dudk added help wanted plugin Issue relates to building Go plugins labels Apr 17, 2021
@lsegal
Copy link
Contributor

lsegal commented Apr 30, 2021

Can confirm that this compiles on Windows, but the plugin is not detectable by VST hosts.

As a sidenote, I'm also not seeing any VSTPluginMain or equivalent type exported symbols in the generated dll:

λ go build --buildmode=c-shared --tags plugin -o plugin.dll .
λ dumpbin /exports plugin.dll
<snip>

Dump of file plugin.dll

File Type: DLL

  Section contains the following exports for plugin.dll

<snip>

    ordinal hint RVA      name

          1    0 00189EF0 _cgo_dummy_export
          2    1 0008ECB0 dispatchPluginBridge
          3    2 0008EE00 getParameterPluginBridge
          4    3 0008EC60 newGoPlugin
          5    4 0008ED40 processDoublePluginBridge
          6    5 0008EDA0 processFloatPluginBridge
          7    6 0008EE60 setParameterPluginBridge

<snip>

AFAIK a VST2.x plugin requires a VSTPluginMain or equivalent exported symbol. Am I missing something here?

@dudk
Copy link
Member Author

dudk commented May 1, 2021

You are absolutely right @lsegal!

As you already discovered in your PR, this entry point exists in include/plugin.c and for Darwin architecture it's exported automatically. I guess that for DLL it behaves differently.

@ryrun
Copy link
Contributor

ryrun commented May 8, 2021

Tried this, too. But plugin crashes in different hosts. Tried Unify x64 and Renoise x64, it just freeze. VSTPluginMain export is there, so it must be something else.

;
; Definition file of plugin.dll
; Automatic generated by gendef
; written by Kai Tietz 2008
;
LIBRARY "plugin.dll"
EXPORTS
VSTPluginMain
_cgo_dummy_export DATA
dispatchPluginBridge
getParameterPluginBridge
newGoPlugin
processDoublePluginBridge
processFloatPluginBridge
setParameterPluginBridge

I used:

  • go version go1.16.4 windows/amd64
  • gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
  • GNU ld (GNU Binutils) 2.30

@dudk
Copy link
Member Author

dudk commented May 10, 2021

Thanks for looking into this @ryrun ! Can you clarify one thing - do those hosts crash when they scan plugins or when you try to instantiate plug-in instance?

@ryrun
Copy link
Contributor

ryrun commented May 10, 2021

@dudk When i try to instantiate plug-in instance. Renoise and Unify simply freeze, need to force close it. Crash was the wrong term, sorry :) Can also test it in FL and Bitwig, if needed.

@dudk
Copy link
Member Author

dudk commented May 10, 2021

Thanks for clarification @ryrun. It would be great if you can check there as well. I can see this behaviour with Renoise on Mac, but only when the second plugin instance is created. That is - the first instance opens fine and works as expected, but when I create the second instance of the very same plugin - Renoise hangs up. Seems like it's the same problem.

@ryrun
Copy link
Contributor

ryrun commented May 10, 2021

Maybe i'm missing something, but how can i specify the uniqueID and version via go? Its missing in the demo.go example. Maybe thats' the reason why these Hosts cant load it.
image
In FL it is freezing, too.

Edit: Ok, it looks the memory gets corrupted. You can see this in the preset count parameter. This could be the reason why:
image

@dudk
Copy link
Member Author

dudk commented May 10, 2021

Thanks for checking it! That's an interesting find. Unique ID and versions are defined in CPlugin, but currently there is no way to actually set them. I'll put up a PR with it soon.

In the current implementation those members are not set to any value. I'm not sure if that can cause such issue because many vst2 plugin manuals don't provide those values either.

EDIT: read your edit, that's an even better catch. Is that happening with time or immediately?

@ryrun
Copy link
Contributor

ryrun commented May 10, 2021

Immediately. VSTHost seems to be good for quick testing. Loaded the plugin 3 times, always different informations about:
image

@dudk I played around abit with your code. It seems malloc is one issue. It allocates memory, but doesn't zero it and its needed to be zero as far as i can see. I've changed all mem allocations to calloc and i can finally load the plugin in Renoise. But it will also freeze, when i create a second instance. So this seems to be another problem.

image

@dudk
Copy link
Member Author

dudk commented May 10, 2021

I tend to think that it's due to vendor string. I'll do a PoC to confirm that.

@ryrun
Copy link
Contributor

ryrun commented May 10, 2021

@dudk It seems malloc is an issue, too. I've edited my post, again sorry :D. Maybe not a good idea, so you will miss this.

@dudk
Copy link
Member Author

dudk commented May 10, 2021

No worries @ryrun 😉 yes, I tend to think that I allocate CPlugin struct wrongfully - it should be 'malloc(sizeof *p)'. I tested this, but it still crashes on the second instance.

To conclude next steps for debugging it:

  • Provide initial values for all fields of the plug-in;
  • Provide unique and version;
  • Provide vendor string dispatch call;

Seems pretty interesting now👀

@ryrun
Copy link
Contributor

ryrun commented May 10, 2021

@dudk
I did a pull request for malloc to calloc #47
This fixes my loading issues.
I'm not sure how i can embed this here. I'm a github noob :D

@ryrun
Copy link
Contributor

ryrun commented May 10, 2021

It still crashes Renoise and FL, when i remove the plugin. But loading seems to be fine now. Was able to playing around with the demo plugin, trying sidechain input.

@ryrun
Copy link
Contributor

ryrun commented May 13, 2021

@dudk Does Renoise also crash on you when you remove the last instance of the plugin? It also happens in FLStudio. Unfortunately there is no information about the crash in the logs.

@dudk
Copy link
Member Author

dudk commented May 13, 2021

@ryrun no, it works fine on Mac. Probably some mach-o bundle magic that handles resource management differently. I assume that it crashes because plugin currently doesn't handle plugClose opcode.

@ryrun
Copy link
Contributor

ryrun commented May 13, 2021

@dudk I tried to debug this crash with gdb and i got this. Not sure how we can fix this:

Thread 66 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 18800.0x29c8]
runtime.usleep2HighRes () at D:/Program Files/go1.16.4/src/runtime/sys_windows_amd64.s:487
487             MOVQ    64(SP), SP
(gdb) where
#0  runtime.usleep2HighRes () at D:/Program Files/go1.16.4/src/runtime/sys_windows_amd64.s:487
#1  0x00000000542c6d9a in runtime.onosstack () at D:/Program Files/go1.16.4/src/runtime/sys_windows_amd64.s:422
#2  0x00000000542a3719 in runtime.usleep (us=86298276) at D:/Program Files/go1.16.4/src/runtime/proc.go:5166
#3  runtime.sysmon () at D:/Program Files/go1.16.4/src/runtime/proc.go:5166
#4  0x000000005429b31a in runtime.mstart1 () at D:/Program Files/go1.16.4/src/runtime/proc.go:1306
#5  0x000000005429b20d in runtime.mstart () at D:/Program Files/go1.16.4/src/runtime/proc.go:1272
#6  0x00000000542ef28c in crosscall_amd64 () at gcc_amd64.S:33
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb) list
482             MOVQ    $0, DX                                  // alertable
483             MOVQ    $0, R8                                  // ptime
484             MOVQ    runtime·_NtWaitForSingleObject(SB), AX
485             CALL    AX
486
487             MOVQ    64(SP), SP
488             RET
489
490     gisnotset:
491             // TLS is not configured. Call usleep2 instead.

Edit: Did some research. Maybe i'm wrong, but it seems that unloading a go c-shared dll causing this crash. Its a known problem: golang/go#11100

Edit2: Maybe this could be a workaround: https://blogs.msmvps.com/vandooren/2006/10/09/preventing-a-dll-from-being-unloaded-by-the-app-that-uses-it/ was mentioned here: golang/go#32497 (comment)

@dudk
Copy link
Member Author

dudk commented May 14, 2021

Now it comes to my mind - I saw the issue you've mentioned before.

It's a pretty interesting workaround. It definitely comes with some price - go runtime would be always running if you. But on another hand, host won't crush 🤷‍♂️ seems like a fair trade off, but needs to be explicitly documented once there.

If you want to play around with it - look into vst_windows.go

@ryrun
Copy link
Contributor

ryrun commented May 14, 2021

@dudk Found a cleaner solution.

Call GetModuleHandleEx with the GET_MODULE_HANDLE_EX_FLAG_PIN flag.
The module stays loaded until the process is terminated, no matter how many times FreeLibrary is called.

See https://stackoverflow.com/a/14436845

I think this would be a better solution for this issue.

@ryrun
Copy link
Contributor

ryrun commented May 14, 2021

@dudk I created a pull request. Not sure if this code is "clean enough". :) With this last fix, all crashes are fixed for me. I can load multiple instance of the demo plugin, remove them one by one. And when the last one was removed, no crash. Gain parameter is working fine. Tested this plugin in Renoise 3.3 and FLStudio 20.8 on a Windows 10 64bit machine.

@ryrun
Copy link
Contributor

ryrun commented May 15, 2021

plugGetParamDisplay is currently not working, returns an empty string. In VSTHost it shows no values.

@dudk
Copy link
Member Author

dudk commented May 15, 2021

@ryrun I think that's because I didn't set any value to Parameter.ValueLabel field. Actually this feature doesn't really work, because it should have the following logic: since all params in VST2 use values of [0;1] interval, plugGetParamDisplay should call a function that will return display value based on current parameter value.

I've created #54 to track it.

@ipg0
Copy link

ipg0 commented Jun 2, 2023

Confirmed demoplugin works on Linux (recognised and functional in Carla host)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted plugin Issue relates to building Go plugins
Projects
None yet
Development

No branches or pull requests

4 participants