Skip to content

Fix PinOne DOF output silently dropped on Linux (sp_open return ignored)#53

Closed
dynajoe wants to merge 1 commit into
vpinball:masterfrom
dynajoe:fix/pinone-sp-open
Closed

Fix PinOne DOF output silently dropped on Linux (sp_open return ignored)#53
dynajoe wants to merge 1 commit into
vpinball:masterfrom
dynajoe:fix/pinone-sp-open

Conversation

@dynajoe

@dynajoe dynajoe commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Fix

NamedPipeServer ignored sp_open()'s return value and wrote to the port handle regardless. sp_get_port_by_name() succeeds for any name (including the class default comm1), so the if (m_serialPort) guard never catches a bad port — a failed open left every write hitting a dead handle. Now: check sp_open(), log the error, and null the handle on failure. (Also unblocks the server thread's accept() on shutdown so teardown doesn't hang.)

Why it matters

On Linux the PinOne's outputs are completely dead while inputs work, and nothing is logged — every DOF write is silently dropped. Addresses vpinball/vpinball#2962.

Related

Part of the PinOne-on-Linux cluster surfaced in #31. The teardown half also addresses the Updater thread did not quit within timeout seen there — an unclean shutdown that can leave a solenoid powered on.

NamedPipeServer ignored sp_open's return value, and the `if (m_serialPort)`
guard is ineffective on Linux because sp_get_port_by_name does not validate
the device — m_serialPort is non-null for any name, including the class
default "comm1" or a Windows "COMx". So a bad/default port name failed to
open silently and every subsequent write vanished into a dead fd: outputs
dead, inputs fine, no error reported.

Changes:
- Check sp_open's return; on failure log the port name + errno and null
  m_serialPort so the existing write guard correctly skips.
- Fix a teardown deadlock: the server thread blocked forever in accept(),
  so StopServer()'s join() never returned. Bound accept() with SO_RCVTIMEO
  so the loop periodically re-checks m_isRunning.
- Log short/failed serial writes.

Verified against a real PinOne over WSL2 usbipd: sp_open("/dev/ttyACM0")
succeeds and the 9-byte DOF frame reaches the serial fd; a bad port name now
logs a clear diagnostic instead of failing silently.
@jsm174

jsm174 commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Hello. Thanks for the PR!

Converting this to draft as per the contributing rules. (I was behind in getting them added as was just done in Visual Pinball).

It's going to take time to review these. libdof is currently is use by several users with a variety of devices, and we have yet to receive issues about this.

Also this definitely needs thorough testing with the actual hardware.

@jsm174
jsm174 marked this pull request as draft July 5, 2026 18:09
@jsm174 jsm174 mentioned this pull request Jul 6, 2026
@dynajoe

dynajoe commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Closing — superseded by #63, which reimplements the sp_open return-value fix (matching PinOne.cs) and additionally resolves the accept() teardown hang (#31) with a select() timeout that also works on macOS, unlike the SO_RCVTIMEO approach here. Thanks for landing the better version.

@dynajoe dynajoe closed this Jul 15, 2026
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