11import ctypes
22import logging
33import os
4+ import signal
45import sys
56import tempfile
67import threading
3334kernel32 = ctypes .WinDLL ('kernel32' , use_last_error = True )
3435logger = logging .getLogger ('pywebview' )
3536cache_dir = None
37+ _sigint_received = False
38+
39+
40+ def _sigint_handler (signum , frame ):
41+ """
42+ Handler for SIGINT signal (Ctrl+C).
43+
44+ Sets a flag that's checked by the timer in the GUI thread. This is necessary because
45+ the signal handler runs in the main thread, but Application.Exit() must be called
46+ from the GUI thread. The timer in create_window() checks this flag periodically and
47+ exits the application when it's set.
48+ """
49+ global _sigint_received
50+ _sigint_received = True
3651
3752
3853def _is_new_version (current_version : str , new_version : str ) -> bool :
@@ -748,11 +763,28 @@ def create():
748763 _main_window_created .set ()
749764
750765 if window .uid == 'master' :
766+
767+ def timer_tick (sender , e ):
768+ # Check if SIGINT was received and exit from GUI thread
769+ global _sigint_received
770+ if _sigint_received :
771+ app .Exit ()
772+
773+ # Create a timer to periodically allow the Python interpreter to run
774+ # This enables the signal handler to be called even when the WinForms event loop is running
775+ timer = WinForms .Timer ()
776+ timer .Interval = 500 # 500ms
777+ timer .Tick += timer_tick
778+ timer .Start ()
779+
751780 app .Run ()
752781
753782 app = WinForms .Application
754783
755784 if window .uid == 'master' :
785+ # Set up Ctrl+C handler in main thread (before starting GUI thread)
786+ signal .signal (signal .SIGINT , _sigint_handler )
787+
756788 if is_chromium :
757789 init_storage ()
758790
@@ -765,7 +797,13 @@ def create():
765797 thread = Thread (ThreadStart (create ))
766798 thread .SetApartmentState (ApartmentState .STA )
767799 thread .Start ()
768- thread .Join ()
800+
801+ # Don't use thread.Join() as it blocks the main thread indefinitely,
802+ # preventing signal handlers from being processed. Instead, periodically
803+ # check if the thread is still alive, which allows the Python interpreter
804+ # to process pending signals (like SIGINT from Ctrl+C)
805+ while thread .IsAlive :
806+ thread .Join (500 )
769807
770808 else :
771809 _main_window_created .wait ()
0 commit comments