HidSharp icon indicating copy to clipboard operation
HidSharp copied to clipboard

Freezing host application (unity freezing)

Open devingDev opened this issue 1 year ago • 6 comments

I'm on windows using Unity 2022.3.28f1 and the current latest commit on this repo. I tried the nuget package and also this, but neither works perfectly inside Unity.

The second time I press play it freezes up and I have to force stop it in task manager.

Found this but i don't know how to fix it right now: https://forum.zer7.com/topic/10126/

devingDev avatar May 23 '24 10:05 devingDev

Fixed it this way if anyone cares: In WinHidManager.cs

  1. Change this part in the Run method:
NativeMethods.MSG msg;
while (true)
{
    int result = NativeMethods.GetMessage(out msg, hwnd, 0, 0);
    if (result == 0 || result == -1) { break; }

    NativeMethods.TranslateMessage(ref msg);
    NativeMethods.DispatchMessage(ref msg);
}

to:

NativeMethods.MSG msg;
_hwnd = hwnd;
while (true)
{
    int result = NativeMethods.GetMessage(out msg, hwnd, 0, 0);
    if (result == 0 || result == -1) { break; }

    NativeMethods.TranslateMessage(ref msg);
    NativeMethods.DispatchMessage(ref msg);
}
  1. After or before the Run method add this:
		static IntPtr _hwnd;
		public static void QuitThisBs()
		{
			uint WM_QUIT = 0x0012;
			if (_hwnd != IntPtr.Zero)
			{ 
				PostMessage(_hwnd, WM_QUIT, IntPtr.Zero, IntPtr.Zero);
			}
		}

		[DllImport("user32.dll")]
		static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
  1. In your code where you exit or want to stop it call WinHidManager.QuitThisBs(); (For me I did it in the OnDestroy method Unity provides, but you can call it anywhere even prematurely while game is still running)

  2. Done!

devingDev avatar May 23 '24 11:05 devingDev

Thanks for your report and investigation on the fix! Care to open a PR with these changes?

benedekkupper avatar May 26 '24 21:05 benedekkupper

Thanks @devingDev !

I can confirm that this fix resolves the issues with Unity Editor on Windows (I am using Unity 2021.3.14)

However, I still had problems accessing the “QuitThisBs” function in WinHidManager from one of my own scripts, i.e. from outside. I have therefore added this to WinHidManager:

At the beginning of the Run method: Application.quitting += OnApplicationQuit;

And a new method:

        private void OnApplicationQuit()
        {
            QuitThisBs();
        }

thanks again for this fix, now I don't have to restart unity every 5 seconds ;)

Jens-roesing avatar Aug 21 '24 15:08 Jens-roesing

There is also a problem with the MacHidManager:

After reloading the domain/assembly, the IOHIDManager is still running and listen for device changes. Some cleanup is required here.

` protected override void Run(Action readyCallback) { readyCallback(); return;

		using (var manager = NativeMethods.IOHIDManagerCreate(IntPtr.Zero).ToCFType())
		{
			RunAssert(manager.IsSet, "HidSharp IOHIDManagerCreate failed.");

			using (var matching = NativeMethods.IOServiceMatching("IOHIDDevice").ToCFType())
			{
				RunAssert(matching.IsSet, "HidSharp IOServiceMatching failed.");

				var devicesChangedCallback = new NativeMethods.IOHIDDeviceCallback(DevicesChangedCallback);
				NativeMethods.IOHIDManagerSetDeviceMatching(manager.Handle, matching.Handle);
				NativeMethods.IOHIDManagerRegisterDeviceMatchingCallback(manager.Handle, devicesChangedCallback, IntPtr.Zero);
				NativeMethods.IOHIDManagerRegisterDeviceRemovalCallback(manager.Handle, devicesChangedCallback, IntPtr.Zero);

				var runLoop = NativeMethods.CFRunLoopGetCurrent();
				NativeMethods.CFRetain(runLoop);
				NativeMethods.IOHIDManagerScheduleWithRunLoop(manager, runLoop, NativeMethods.kCFRunLoopDefaultMode);
				try
				{
					readyCallback();
					NativeMethods.CFRunLoopRun();
				}
				finally
				{
					NativeMethods.IOHIDManagerUnscheduleFromRunLoop(manager, runLoop, NativeMethods.kCFRunLoopDefaultMode);
					NativeMethods.CFRelease(runLoop);
				}

				GC.KeepAlive(devicesChangedCallback);
			}
		}
	}

`

PolyCrusher avatar Oct 10 '24 07:10 PolyCrusher

Thanks @devingDev !

I can confirm that this fix resolves the issues with Unity Editor on Windows (I am using Unity 2021.3.14)

However, I still had problems accessing the “QuitThisBs” function in WinHidManager from one of my own scripts, i.e. from outside. I have therefore added this to WinHidManager:

At the beginning of the Run method: Application.quitting += OnApplicationQuit;

And a new method:

        private void OnApplicationQuit()
        {
            QuitThisBs();
        }

thanks again for this fix, now I don't have to restart unity every 5 seconds ;)

How did you add Application.quitting to the Run method in WinHidManager? I do not seem to have one?

OnurRafet avatar Oct 21 '24 14:10 OnurRafet

@OnurRafet

Just like this, right at the start a register to the quitting event, only works with in Unity because "Application" is from using UnityEngine;

        private void OnApplicationQuit()
        {
            QuitThisBs();
        }

        protected override void Run(Action readyCallback)
        {
            UnityEngine.Application.quitting += OnApplicationQuit;

            // Rest of the run function ...
        }

Jens-roesing avatar Apr 25 '25 12:04 Jens-roesing