Skip to content

Fixes from development branch#77

Merged
thiagoralves merged 4 commits into
mainfrom
development
Jan 15, 2026
Merged

Fixes from development branch#77
thiagoralves merged 4 commits into
mainfrom
development

Conversation

@thiagoralves
Copy link
Copy Markdown
Contributor

This pull request improves the safety and robustness of plugin driver lifecycle management, especially around the use of the Python Global Interpreter Lock (GIL) and destruction order. The changes ensure that Python-related operations are only performed when the Python interpreter is initialized, and that resource cleanup avoids potential deadlocks and undefined behavior.

Key improvements include:

Python GIL Management and Safety:

  • All plugin driver functions (init, start, stop, restart, and destroy) now check if Python is initialized (Py_IsInitialized()) before acquiring or releasing the GIL, preventing undefined behavior if Python is not available. [1] [2] [3] [4] [5] [6] [7]
  • The GIL is only released if it was previously acquired, and all GIL state variables are initialized to avoid compiler warnings. [1] [2] [3]

Resource Cleanup and Deadlock Prevention:

  • In plugin_driver_destroy, the mutex and driver memory are freed early if there are no plugins, preventing resource leaks.
  • In unload_plc_program, the order of operations is changed to stop plugins before acquiring the buffer mutex, preventing a potential deadlock when plugins (like S7Comm) access the mutex during shutdown.

Error Handling Improvements:

  • When plugin initialization or cleanup fails, the GIL is properly released only if it was acquired, ensuring consistent interpreter state and preventing resource leaks. [1] [2] [3] [4]

These changes collectively make the plugin driver more robust, especially in mixed native/Python plugin environments and in scenarios where the Python interpreter may or may not be initialized.

thiagoralves and others added 4 commits January 14, 2026 13:40
Two issues fixed:

1. Deadlock with S7Comm plugin (plc_state_manager.c):
   - unload_plc_program() tried to acquire buffer_mutex BEFORE stopping
     plugins, but S7Comm's RWArea callback holds this mutex during
     client reads, causing deadlock
   - Fix: Call plugin_driver_stop() before acquiring the mutex

2. Hang when stopping without Python plugins (plugin_driver.c):
   - plugin_driver_init/start/stop/destroy called Python GIL functions
     even when no Python plugins exist or Python wasn't initialized
   - Fix: Add has_python_plugin && Py_IsInitialized() checks before
     all Python GIL operations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove unnecessary initialization of PyGILState_STATE to 0 (opaque type)
- Add NULL check for main_tstate before PyEval_RestoreThread() to prevent
  undefined behavior if destroy is called without start

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use the explicit enum value PyGILState_LOCKED instead of 0 to satisfy
compiler warning while being semantically correct. The variable is only
used when have_gil/python_initialized is true, but the compiler's static
analysis can't prove this across all control flow paths.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
fix: Prevent deadlock when stopping PLC with plugins
@thiagoralves thiagoralves merged commit ea6e027 into main Jan 15, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant