cmbruns / pyopenvr

Unofficial python bindings for Valve's OpenVR virtual reality SDK
BSD 3-Clause "New" or "Revised" License
245 stars 39 forks source link

Windows: when I close SteamVR, my script closes too #70

Closed mann1x closed 4 years ago

mann1x commented 4 years ago

I'm using Windows 10 1903 with Python 3.74 and SteamVR beta 1.8.12, pyopenvr 1.7.1501.

From my understanding of this issue:

https://github.com/ValveSoftware/openvr/issues/878

And the referenced on the OBS input plugin:

https://github.com/baffler/OBS-OpenVR-Input-Plugin/issues/3

There should be a way to keep running the process if SteamVR is closed. Right now I couldn't find how. I'd like my script to query some info from OpenVR about the Basestations and the pose.

Not matter if the acknowledgeQuit_Exiting() is called on VREvent_Quit, once openvr.shutdown() is called the script is killed. If I remove the shutdown (shutdown = False) SteamVR hangs in "Exiting" and the script goes on till about 30 seconds till is killed and SteamVR closes.

Am I missing something on how to keep it on? Any help would be appreciated, thanks.

Also I'm wondering how to properly initialize and, eventually if not killed, re-initalize with the init function or in any other way.

In the script attached I just try for the init function and this causes a memory leak. It's even more obvious in the script with testreinit = True. Every time an init is issued some memory between 100KB and 300KB is allocated and never released. Setting to None the vr_system variable doesn't help and it's not recovered either by the garbage collector. It's probably a bigger issue if called in a loop, probably shouldn't be done for starting. But in general would be nice to know if it can be freed somehow, even if allocated once.

Also while checking SteamVR opening and closing I noticed very often there's no event or pose updates, sometimes the connection is established but the Quit event is never received. I wonder if I'm not using it how it should be.

testloop.txt

risa2000 commented 4 years ago

Not matter if the acknowledgeQuit_Exiting() is called on VREvent_Quit, once openvr.shutdown() is called the script is killed.

Acknowledging VREvent_Quit by calling shutdown is a correct way to "detach" from SteamVR server (https://github.com/ValveSoftware/openvr/issues/1061).

The problem with your code is that after it calls shutdown, it still uses vr_system interface, in particular in:

            vr_system.pollNextEvent(event)

where, not only vr_system is no longer valid, but an attempt to call it, ends up with an invalid memory access, because the IVRSystem interface, which backs up vr_system was unallocated when shutdown freed vrclient_x64.dll.

So basically your program (Python interpreter) dies from an access violation error.

The fix is simple, once you call shutdown, you cannot use any interface, until you openvr.init it again (which will also load vrclient_x64.dll again).

Just to prove the idea I patched your testloop with this:

$ diff -ru testloop.py testloop_fix.py
--- testloop.py 2019-10-15 00:11:45.296730100 +0200
+++ testloop_fix.py     2019-10-15 00:08:40.655332500 +0200
@@ -39,6 +39,7 @@
                 if shutdown:
                     openvr.shutdown()
                     print("Shutdown sent")
+                    raise "OpenVR shutdown"
             elif event.eventType == openvr.VREvent_QuitAcknowledged:
                 print("ACK received eventType={0}".format(event.eventType))
                 print("eventAgeSeconds={0}".format(event.eventAgeSeconds))

and it works as expected (i.e. attaching to SteamVR when SteamVR starts, and dropping the connection, when SteamVR is terminated).

risa2000 commented 4 years ago

@mann1x, please create separate issues for the memory leak and/or the events.

mann1x commented 4 years ago

@risa2000 thanks a lot for your help! I opened another issue for the memory issue with init:

https://github.com/cmbruns/pyopenvr/issues/71