Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added
- `WinMM` engine
### Changed
- `run` function in NavaThread
- `stop` function in NavaThread
- `README.md` updated
- Test system modified
- `Python 3.6` support dropped
Expand Down
27 changes: 20 additions & 7 deletions nava/thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def run(self):
try:
if self._target is not None:
if self._engine == Engine.WINSOUND or self._engine == Engine.WINMM:
_ = self._target(*self._args, **self._kwargs)
self._target(*self._args, **self._kwargs)
else:
while True:
self._play_process = self._target(*self._args, **self._kwargs)
Expand All @@ -62,16 +62,29 @@ def stop(self):
elif self._engine == Engine.WINMM:
self._force_stop = True
# The alias is scoped to the MCI (Media Control Interface) context of the thread that created it.
# So the main thread can’t “see the alias created in the worker thread.
# So the main thread can't "see" the alias created in the worker thread.
else:
if self._play_process is not None:
if self._play_process:
# Best-effort: close all standard streams
try:
self._play_process.stdout.close()
self._play_process.stdin.close()
self._play_process.stderr.close()
self._play_process.kill()
self._play_process.terminate()
except ProcessLookupError:
except Exception: # nosec B110 - Best effort cleanup, ignore all errors
# Streams may be None, already closed, or OS-specific issues
pass

# Try graceful termination
try:
self._play_process.terminate()
self._play_process.wait(timeout=1)
except Exception:
# Fallback to force kill - catch any process-related errors
try:
self._play_process.kill()
self._play_process.wait()
except Exception: # nosec B110 - Best effort cleanup, ignore all errors
# Process already terminated or any other issues
pass
finally:
self._play_process.wait()
self._play_process = None