pyappify 1.0.3__tar.gz → 1.0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyappify
3
- Version: 1.0.3
3
+ Version: 1.0.4
4
4
  Summary: My awesome Python application
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -8,6 +8,7 @@ import shutil
8
8
  import urllib.request
9
9
  import zipfile
10
10
  import threading
11
+ import time
11
12
 
12
13
  app_version = os.environ.get("PYAPPIFY_APP_VERSION")
13
14
  app_starting_version = os.environ.get("PYAPPIFY_APP_STARTING_VERSION") or app_version
@@ -78,10 +79,67 @@ def kill_pyappify():
78
79
  log.info(f"Attempting to terminate process with PID: {pid}")
79
80
  try:
80
81
  os.kill(pid, signal.SIGTERM)
82
+ if not _wait_for_process_exit(pid):
83
+ log.warning(f"Timed out waiting for process with PID {pid} to exit.")
81
84
  except Exception as e:
82
85
  log.error(f"Failed to terminate process with PID {pid}: {e}")
83
86
  pass
84
87
 
88
+
89
+ def _wait_for_process_exit(process_pid, timeout=30):
90
+ if sys.platform == "win32" and ctypes:
91
+ synchronize = 0x00100000
92
+ wait_timeout = 0x00000102
93
+ wait_failed = 0xFFFFFFFF
94
+ ctypes.windll.kernel32.OpenProcess.argtypes = (
95
+ ctypes.c_uint,
96
+ ctypes.c_bool,
97
+ ctypes.c_ulong,
98
+ )
99
+ ctypes.windll.kernel32.OpenProcess.restype = ctypes.c_void_p
100
+ ctypes.windll.kernel32.WaitForSingleObject.argtypes = (
101
+ ctypes.c_void_p,
102
+ ctypes.c_uint,
103
+ )
104
+ ctypes.windll.kernel32.WaitForSingleObject.restype = ctypes.c_uint
105
+ ctypes.windll.kernel32.CloseHandle.argtypes = (ctypes.c_void_p,)
106
+ ctypes.windll.kernel32.CloseHandle.restype = ctypes.c_bool
107
+ handle = ctypes.windll.kernel32.OpenProcess(synchronize, False, process_pid)
108
+ if handle:
109
+ try:
110
+ result = ctypes.windll.kernel32.WaitForSingleObject(
111
+ handle, int(timeout * 1000)
112
+ )
113
+ if result == wait_failed:
114
+ return False
115
+ return result != wait_timeout
116
+ finally:
117
+ ctypes.windll.kernel32.CloseHandle(handle)
118
+
119
+ deadline = time.monotonic() + timeout
120
+ while time.monotonic() < deadline:
121
+ try:
122
+ os.kill(process_pid, 0)
123
+ except OSError:
124
+ return True
125
+ time.sleep(0.1)
126
+ return False
127
+
128
+
129
+ def _replace_executable(source_path, target_path, timeout=30):
130
+ deadline = time.monotonic() + timeout
131
+ last_error = None
132
+ while True:
133
+ try:
134
+ shutil.move(source_path, target_path)
135
+ return
136
+ except PermissionError as e:
137
+ last_error = e
138
+ if time.monotonic() >= deadline:
139
+ raise last_error
140
+ time.sleep(0.25)
141
+
142
+
85
143
  def hide_pyappify():
86
144
  if pid:
87
145
  log = _get_logger()
@@ -154,7 +212,7 @@ def upgrade(to_version, executable_sha256, executable_zip_urls, stop_event=None)
154
212
  return
155
213
 
156
214
  kill_pyappify()
157
- shutil.move(found_executable_path, pyappify_executable)
215
+ _replace_executable(found_executable_path, pyappify_executable)
158
216
  log.info(f"pyappify Upgrade success")
159
217
  except Exception as e:
160
218
  log.error(f"pyappify Upgrade failed: {e}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyappify
3
- Version: 1.0.3
3
+ Version: 1.0.4
4
4
  Summary: My awesome Python application
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pyappify"
7
- version = "1.0.3"
7
+ version = "1.0.4"
8
8
  description = "My awesome Python application"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.7"
File without changes
File without changes
File without changes
File without changes