Skip to content

Ensure libgpiod resources are cleaned up on exit - #1109

Merged
makermelissa merged 1 commit into
adafruit:mainfrom
makermelissa-ai-assistant:fix-libgpiod-cleanup
Apr 22, 2026
Merged

Ensure libgpiod resources are cleaned up on exit#1109
makermelissa merged 1 commit into
adafruit:mainfrom
makermelissa-ai-assistant:fix-libgpiod-cleanup

Conversation

@makermelissa-ai-assistant

Copy link
Copy Markdown
Contributor

Summary

Fixes #435 — GPIO lines held by libgpiod and PulseIn subprocesses were not being properly released when scripts were interrupted (Ctrl+C, SIGTERM), causing "Unable to set line to input" errors on subsequent runs.

Problem

When a Python script using Blinka's GPIO or PulseIn is interrupted:

  1. libgpiod 1.x Pin had no __del__ or deinit() method, so GPIO lines were never released unless init() was called again to reconfigure
  2. libgpiod Chip objects (both 1.x and 2.x) were never explicitly closed
  3. PulseIn subprocesses relied solely on atexit handlers which don't fire on SIGTERM, and the deinit() method would crash if called twice
  4. digitalio.DigitalInOut.deinit() just did del self._pin which doesn't release GPIO lines on libgpiod 1.x

Changes

  • libgpiod Pin (1.x & 2.x): Add deinit() method to explicitly release lines and close chips. Add __del__ as a GC safety net.
  • libgpiod Chip (1.x & 2.x): Add __del__ to close chip handles on garbage collection.
  • PulseIn (bcm283x, meson_g12, a311d): Add __del__ safety net. Make deinit() idempotent (safe to call multiple times). Add SIGTERM signal handler alongside existing atexit handler to ensure subprocesses and message queues are cleaned up.
  • digitalio.DigitalInOut: deinit() now calls pin.deinit() when available instead of just deleting the reference.

Add proper cleanup for libgpiod GPIO lines, chips, and PulseIn
subprocesses to prevent 'Unable to set line to input' errors when
scripts are interrupted with Ctrl+C or SIGTERM and then restarted.

Changes:
- Add __del__/deinit to libgpiod Pin classes (1.x and 2.x) to release
  GPIO lines and close chips when Pin objects are garbage collected
- Add __del__ to libgpiod Chip classes (1.x and 2.x) to close chip
  handles on garbage collection
- Add __del__ to all PulseIn implementations (bcm283x, meson_g12,
  a311d) as a safety net for cleanup when deinit() is not called
- Make PulseIn.deinit() idempotent (safe to call multiple times)
- Add SIGTERM signal handler to PulseIn modules so subprocesses and
  message queues are cleaned up even when the process is killed
- Fix digitalio.DigitalInOut.deinit() to call pin.deinit() instead
  of just deleting the reference, ensuring proper resource release

Fixes adafruit#435

@makermelissa makermelissa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@makermelissa
makermelissa merged commit ca26a49 into adafruit:main Apr 22, 2026
1 check 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.

Make sure to kill libgpiod threads

2 participants