Skip to content

Feature/general threading improvements#18

Open
khauersp wants to merge 27 commits into
masterfrom
feature/general-threading-improvements
Open

Feature/general threading improvements#18
khauersp wants to merge 27 commits into
masterfrom
feature/general-threading-improvements

Conversation

@khauersp

@khauersp khauersp commented Jun 4, 2026

Copy link
Copy Markdown
Owner

This pull request introduces significant improvements to the threading, timer management, and lifecycle handling in the J1939 ECU implementation. The main changes include splitting protocol and timer handling into separate threads for better isolation, introducing thread-safe mechanisms for timer events and subscriber management, and adding a robust dependent lifecycle registry to ensure proper shutdown of helper objects. Additionally, all timeouts and deadlines now use time.monotonic() for improved reliability, and critical shared resources are protected with appropriate locks.

Threading and Timer Management Improvements:

  • Split the original job thread into two dedicated threads: a protocol thread for TP/BAM timeout management and a timer thread for application cyclic callbacks, ensuring that slow user callbacks do not interfere with protocol deadlines. Timer events are now managed using a heap-based priority queue (heapq) for efficient scheduling. [1] [2] [3]
  • All timeouts, deadlines, and timer events now use time.monotonic() instead of time.time() to avoid issues with system clock changes. [1] [2] [3] [4] [5]

Thread Safety and Synchronization:

  • Introduced thread locks (threading.RLock and threading.Lock) to protect access to timer events, subscribers, and protocol buffers, ensuring safe concurrent access from multiple threads. [1] [2] [3] [4] [5] [6] [7]

Lifecycle and Shutdown Handling:

  • Added a dependent lifecycle registry to the ECU, allowing helper objects to register for shutdown callbacks. Registered dependents are stopped in LIFO order before the ECU's own threads are shut down, with robust error handling during shutdown. [1] [2]
  • Added register_dependent and unregister_dependent methods to both the ECU and ControllerApplication classes for managing dependent helpers. [1] [2]

General Codebase Improvements:

  • Improved documentation and comments throughout the codebase to clarify thread responsibilities, locking, and shutdown procedures. [1] [2]

These changes collectively enhance the robustness, correctness, and maintainability of the J1939 ECU implementation, especially in multi-threaded and complex application scenarios.

RaulSMS added 4 commits May 20, 2026 12:54
To support agentic development
Extend the DTC class and Dm1 sender/receiver to handle SAE J1939-73 SPN
conversion methods 1, 2, 3, and 4 (previously only CM 4 / CM-bit-clear
was supported and other methods were logged as errors on receive). TX
takes an optional per-DTC 'cm' key (default 4); RX disambiguates the
CM-bit-set case via a new Dm1(rx_cm_bit_set=...) constructor arg.
Add support for all four DM1 SPN conversion methods
@khauersp khauersp closed this Jun 10, 2026
@khauersp khauersp reopened this Jun 10, 2026
@khauersp khauersp force-pushed the feature/general-threading-improvements branch from 06adcdf to d4cb879 Compare June 17, 2026 14:35
@khauersp khauersp force-pushed the feature/general-threading-improvements branch from d4cb879 to 950845d Compare June 17, 2026 15:48
khauersp and others added 6 commits June 17, 2026 11:52
With the two-thread model introduced in this branch, the protocol thread
iterates _snd_buffer in async_job_thread concurrently with send_pgn being
called from a user/timer thread. The check-then-write on _snd_buffer was
unprotected, creating a live race (RuntimeError: dictionary changed size
during iteration on CPython).

j1939_22.py already wraps its send_pgn buffer writes with _buffer_lock;
this commit brings j1939_21.py to the same standard.

CAN I/O (_send_tp_bam / _send_tp_rts) is intentionally kept outside the
lock to avoid holding it during I/O.
Two new tests in test_threading.py covering the race condition fixed in
the previous commit:

- test_send_pgn_concurrent_no_crash: 4 threads hammer send_pgn while the
  protocol thread is running; verifies no RuntimeError or crash.
- test_send_pgn_j1939_21_buffer_lock_no_race: two threads race to send to
  the same src/dst pair simultaneously; verifies the check-then-write is
  atomic (exactly one succeeds, one is rejected).
#11)

python-can v4.2.0 renamed the Bus() kwarg from 'bustype' to 'interface'
and scheduled 'bustype' for removal in v5.0. Update all examples and the
connect() docstring, and bump the minimum version requirement in setup.py.

Fixes #9.
…12)

Covers issue #8 — device_address_preferred=0 is falsy in Python, so a
bare truthiness check silently skipped the bypass, leaving the CA in
State.NONE. The fix (is not None guard) was already applied; this test
pins the behaviour so it cannot regress.
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.

2 participants