Skip to content

Update timeout mechanism for serial on Linux#156

Merged
sgunes-wirepas merged 3 commits into
masterfrom
fix/linux_serial
Jul 6, 2026
Merged

Update timeout mechanism for serial on Linux#156
sgunes-wirepas merged 3 commits into
masterfrom
fix/linux_serial

Conversation

@sgunes-wirepas

Copy link
Copy Markdown
Contributor

This should prevent potential deadlocks caused by read() blocking with no timeout. See individual commits for details.

Earlier, serial interface was configured with termios, and ioctl_tty
(TCSETS2/TCGETS2 ioctl calls) was used for configuring a custom baud
rate because it is not possible with termios.

There have been observations on some kernels that the TCSETS2 with
custom baud rate reset the earlier VMIN/VTIME parameters set via
termios. This should fix that since everything is now made with one
ioctl call.

Since this is linux specific serial implementation and we anyway depend
on termios2 here, there is no harm in removing the termios part. This
also simplifies the code.
Previously, read() was configured to block with a timeout using
VMIN/VTIME and ICANON(c_lflag) attributes.

These attributes belong to the shared serial device and they might be
changed by another process. This can make read() calls block without a
timeout.

If read() starts blocking forver, it can cause a deadlock when multiple
threads try to send a dualmcu api request and wait for response bytes.
Since wpc_internal.c:check_if_timeout_reached_locked() is called in
these threads after writing or reading bytes, the timeout mechanism
might never kick in and program will not exit.

TCSETS2 ioctl call might also report success if *any* of the given
attributes were updated so it is not guaranteed that the serial has
correct attributes after the set_interface_attribs() call. However, the
other attributes being invalid is likely to cause data corruptions and
other errors which should be more visible elsewhere (as opposed to being
stuck in read()).
This is similar to the earlier behavior; read() failures are treated as
timeouts. Therefore, using debug log level for now.

}

return (remaining_sec * 1000) + (remaining_nsec / 1000000);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In our case it is fine as value are small, but is the compiler happy to silently convert time_t * 1000 as an int ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point, thanks! No warnings with the current sink-service build. I think it would be good to enable the -Wconversion flag (that introduces the warning for above line) and add explicit casts so avoid accidental conversions, but better in another commit because there are existing places in the code that would need to be checked.

@sgunes-wirepas sgunes-wirepas merged commit 8ff8124 into master Jul 6, 2026
5 checks passed
@sgunes-wirepas sgunes-wirepas deleted the fix/linux_serial branch July 6, 2026 12:13
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