r0x0r/pywebview

Crash on Windows when opened from system tray

simonrob opened this issue · 6 comments

Specification

  • pywebview version: 3.4
  • operating system: Windows 10
  • web renderer: Unknown - whatever is the default

Description

I use pywebview along with pystray (0.17.3) as part of a script that occasionally needs to pop up a login window. Because both pywebview and pystray need to run on the main thread, I open the webview from a click on the system tray icon, as shown in the basic example below. This action runs on the main thread, and on macOS and Ubuntu it works with no issues. On Windows it gives the following error:

Unhandled Exception: Python.Runtime.PythonException: OSError : [WinError 1402] Invalid cursor handle.
   at Python.Runtime.Dispatcher.Dispatch(ArrayList args)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

A minimum example to demonstrate the issue is given below. Run this code on Windows and you will see a black square appear in the system tray. Right-click the icon and click the Webview option to trigger the crash. I've also added the thread names to show that both pystray and pywebview are running on the main thread:

import pystray, webview, threading
from PIL import Image

def click(icon, item):
    print('pywebview thread:', threading.current_thread().__class__.__name__)
    window = webview.create_window('Woah dude!', 'https://pywebview.flowrl.com')
    webview.start()

if __name__ == '__main__':
    print('pystray thread:', threading.current_thread().__class__.__name__)
    pystray.Icon('test', Image.new('RGB', (16, 16)), menu=pystray.Menu(pystray.MenuItem('Webview', click))).run()

Practicalities

  • YES/NO I am willing to work on this issue myself.
    Possibly, if you can point to where to begin

  • YES/NO I am prepared to support this issue financially.
    If needed

Specification

  • pywebview version: 3.8.6
  • operating system: Windows 10
  • web renderer: Unknown - whatever is the default

I have same problem

import webview

webview.create_window('Hello world', 'https://pywebview.flowrl.com/')
webview.start()
python main.py

Необработанное исключение: Python.Runtime.PythonException: Exception : Сбой при удаленном вызове процедуры. (Исключение из HRESULT: 0x800706BE)
   в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   в Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlProcess.<CreateWebViewControlHostAsync>d__16.MoveNext()
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
   в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   в Microsoft.Toolkit.Forms.UI.Controls.WebViewControlProcessExtensions.CreateWebViewControlHost(WebViewControlProcess process, IntPtr hostWiНеобработанное исключение: Python.Runtime.PythonException: Exception : Сбой при удаленном вызове процедуры. (Исключение из HRESULT: 0x800706BE
)
   в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   в Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlProcess.<CreateWebViewControlHostAsync>d__16.MoveNext()
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
   в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   в Microsoft.Toolkit.Forms.UI.Controls.WebViewControlProcessExtensions.CreateWebViewControlHost(WebViewControlProcess process, IntPtr hostWi
ndowHandle, Rectangle bounds)
   в Microsoft.Toolkit.Forms   в Microsoft.Toolkit.Forms.UI.Controls.WebViewControlProcessExtensions.CreateWebViewControlHost(WebViewControlProcess process, IntPtr host
WindowHandle, Rectangle bounds)
   в Microsoft.Toolkit.Forms.UI.Controls.WebView.Initialize()
   в Microsoft.Toolkit.Forms.UI.Controls.WebView.System.ComponentModel.ISupportInitialize.EndInit()
   в Python.Runtime.Dispatcher.Dispatch(ArrayList args)
   в System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preser
veSyncCtx)
   в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCt
x)
   в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   в System.Threading.ThreadHelper.ThreadStart()

   в Microsoft.Toolkit.Forms.UI.Controls.WebViewControlProcessExtensions.CreateWebViewControlHost(WebViewControlProcess process, IntPtrh
ostWindowHandle, Rectangle bounds)
   в Microsoft.Toolkit.Forms.UI.Controls.WebViewControlProcessExtensions.CreateWebViewControlHost(WebViewControlProcess process, IntPtr
   в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   в Microsoft.Toolkit.Forms.UI.Controls.WebViewControlProcessExtensions.CreateWebViewControlHost(WebViewControlProcess process, IntPtr hostWin
dowHandle, Rectangle bounds)
   в Microsoft.Toolkit.Forms.UI.Controls.WebView.Initialize()
   в Microsoft.Toolkit.Forms.UI.Controls.WebView.System.ComponentModel.ISupportInitialize.EndInit()
   в Python.Runtime.Dispatcher.Dispatch(ArrayList args)
   в System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveS
yncCtx)
   в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   в System.Threading.ThreadHelper.ThreadStart()

r0x0r commented

@simonrob both libraries need to be run on a main thread. threading cannot do that, but using multiprocessing combined with a queue to pass data between processes might do the trick.

@r0x0r thanks, but as the example shows, both are running on the main thread, and work on Linux and macOS which has the same requirements. (I don't think the other reply in this issue is actually the same problem.)

I looked at this again and found that it may actually not be anything to do with the thread, but actually some underlying pywebview incompatibility with pystray on Windows.

On Windows, simply adding import pystray and trying to start the webview causes this crash.

Pystray itself works fine when both are imported together (in either order).

What could be going on here?

Just to follow up, as discussed in a pystray issue, this is caused by windll.user32.DestroyIcon(icon_handle) in winforms.py.

Should this call be conditional on icon_handle != 0 like the icon creation which happens a few lines above? The only documentation I can find seems to suggest that DestroyIcon should always be called after ExtractIcon, but presumably this is not the case if there is no handle returned.

r0x0r commented

I have no idea about this either, but if this solves the problem then it is fine by me. Thanks for the PR!