Skip to content

Support systemd notifications#23

Open
RWebster-Noble wants to merge 4 commits into
BryanJacobs:mainfrom
RWebster-Noble:systemd-notify
Open

Support systemd notifications#23
RWebster-Noble wants to merge 4 commits into
BryanJacobs:mainfrom
RWebster-Noble:systemd-notify

Conversation

@RWebster-Noble
Copy link
Copy Markdown

@RWebster-Noble RWebster-Noble commented Mar 6, 2026

Fixes an issue where systemd would incorrectly detect the service as hung, causing restart loops.
Also updated code to allow the service to be shutdown cleanly.

Changes

Event Loop Management

  • Replaced manual event loop handling with asyncio.run() for cleaner shutdown and automatic cleanup

Systemd Integration

  • Added Type=notify to the service file to support service state tracking
  • Implemented sd-notify for systemd ready-state signaling
  • Added graceful shutdown handlers for SIGTERM/SIGINT signals to ensure clean termination
  • Added some informational logs

Service

  • Updated service example to use notify type

Dependencies

  • Added sd-notify = "^0.1.0"

@RWebster-Noble RWebster-Noble changed the title Systemd notify Support systemd notify Mar 6, 2026
@RWebster-Noble RWebster-Noble changed the title Support systemd notify Support systemd notifications Mar 6, 2026
@BryanJacobs
Copy link
Copy Markdown
Owner

BryanJacobs commented Mar 6, 2026

This looks clean, but I think it has a bug: because systemd is not a dependency of the Python package, there's no guarantee it's installed. That's fine because you've added a dynamic import guard.

But the systemd unit is changed to use notify as the startup type. The notification will never be received if the sd_notify package isn't installed. The service will be stuck in the starting state.

Your description of the PR says you've added sd-notify as a dependency but you have not.

@RWebster-Noble
Copy link
Copy Markdown
Author

Your description of the PR says you've added sd-notify as a dependency but you have not.

Opps, got a bit overzealous with my tidying up.

I've added that now.

I also realised that doing a optional import is a bit redundant with this being a dependency so I just made that a regular import.


I decided to do a test by installing this on a fresh Ubuntu 24.04 VM and got this error:

c/_cffi_backend.c:6112:9: error: implicit declaration of function '_PyErr_WriteUnraisableMsg'; did you mean 'PyErr_WriteUnraisable'? [-Wimplicit-function-declaration]

So to fix that I added an updated dependency for cffi ^1.17.0 for Python 3.14 compatibility.

Here's my full test after fixing that:

sudo apt-get update
sudo apt-get install -y pipx gcc libffi-dev libpcsclite-dev swig python3-dev pcscd

pipx ensurepath
export PATH=$HOME/.local/bin:$PATH
pipx install poetry

cd fido2-hid-bridge/

poetry install

sudo mkdir -p /opt/fido2-hid-bridge
sudo cp -r . /opt/fido2-hid-bridge/
sudo cp fido2-hid-bridge.service /etc/systemd/system/
cd /opt/fido2-hid-bridge && sudo -E $HOME/.local/bin/poetry install

sudo systemctl daemon-reload
sudo systemctl enable --now fido2-hid-bridge

Test stop and start:

$ sudo systemctl status fido2-hid-bridge.service

● fido2-hid-bridge.service - Fido2 to HID bridge
     Loaded: loaded (/etc/systemd/system/fido2-hid-bridge.service; enabled; preset: enabled)
     Active: active (running) since Sun 2026-03-08 11:26:09 UTC; 1min 20s ago
   Main PID: 710 (fido2-hid-bridg)
      Tasks: 1 (limit: 4601)
     Memory: 31.1M (peak: 31.4M)
        CPU: 129ms
     CGroup: /system.slice/fido2-hid-bridge.service
             └─710 /opt/fido2-hid-bridge/.venv/bin/python /opt/fido2-hid-bridge/.venv/bin/fido2-hid-bridge

Mar 08 11:26:08 systemd[1]: Starting fido2-hid-bridge.service - Fido2 to HID bridge...
Mar 08 11:26:09 fido2-hid-bridge[710]: INFO:UHIDDevice:initializing device
Mar 08 11:26:09 fido2-hid-bridge[710]: INFO:UHIDDevice:(UHID_CREATE2) create UHIDDevice(vid=39321, pid=39321, name=FIDO2 Virtual USB Device, uniq=UHIDDevice_b586f6c9-fffa-4721-a2b6-cee42be0f15a)
Mar 08 11:26:09 fido2-hid-bridge[710]: INFO:root:FIDO2 HID Bridge started successfully
Mar 08 11:26:09 systemd[1]: Started fido2-hid-bridge.service - Fido2 to HID bridge.

$ sudo systemctl stop fido2-hid-bridge.service

$ sudo systemctl status fido2-hid-bridge.service --no-pager 
○ fido2-hid-bridge.service - Fido2 to HID bridge
     Loaded: loaded (/etc/systemd/system/fido2-hid-bridge.service; enabled; preset: enabled)
     Active: inactive (dead) since Sun 2026-03-08 11:27:43 UTC; 2s ago
   Duration: 1min 34.129s
    Process: 710 ExecStart=/opt/fido2-hid-bridge/.venv/bin/fido2-hid-bridge (code=exited, status=0/SUCCESS)
   Main PID: 710 (code=exited, status=0/SUCCESS)
        CPU: 138ms

Mar 08 11:26:08 systemd[1]: Starting fido2-hid-bridge.service - Fido2 to HID bridge...
Mar 08 11:26:09 fido2-hid-bridge[710]: INFO:UHIDDevice:initializing device
Mar 08 11:26:09 fido2-hid-bridge[710]: INFO:UHIDDevice:(UHID_CREATE2) create UHIDDevice(vid=39321, pid=39321, name=FIDO2 Virtual USB Device, uniq=UHIDDevice_b586f6c9-fffa-4721-a2b6-cee42be0f15a)
Mar 08 11:26:09 fido2-hid-bridge[710]: INFO:root:FIDO2 HID Bridge started successfully
Mar 08 11:26:09 systemd[1]: Started fido2-hid-bridge.service - Fido2 to HID bridge.
Mar 08 11:27:43 systemd[1]: Stopping fido2-hid-bridge.service - Fido2 to HID bridge...
Mar 08 11:27:43 fido2-hid-bridge[710]: INFO:root:Received signal SIGTERM, shutting down...
Mar 08 11:27:43 fido2-hid-bridge[710]: INFO:root:FIDO2 HID Bridge shutting down...
Mar 08 11:27:43 systemd[1]: fido2-hid-bridge.service: Deactivated successfully.
Mar 08 11:27:43 systemd[1]: Stopped fido2-hid-bridge.service - Fido2 to HID bridge.

I also set PYTHONUNBUFFERED per the advice here.

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