serial icon indicating copy to clipboard operation
serial copied to clipboard

setSignals() synchronicity (or lack thereof)

Open basilhussain opened this issue 8 months ago • 4 comments

I would like to raise an issue seeking some clarification on whether the API specification intends any synchronicity in how setSignals() applies the specified signal states to a serial port, and discuss potential disjunction between how a user may expect it to behave and how it actually behaves.

The nature of the setSignals() API method - taking a single dictionary argument containing one or more signal states - may be likely to lead a user to assume that the new states of multiple signals they specify in the argument are all applied synchronously. That is, an assumption that the change in state of all specified signals will occur at the exact same moment; because new signal states are specified all at once, ergo they are applied all at once, no?

However, reality does not meet this potential expectation, due to current implementations (i.e. Chromium-based browsers) performing signal state change operations only in a discrete sequential manner. For example, in Chrome and Edge, if one changes both dataTerminalReady and requestToSend in the same setSignals() call, the former is always toggled before the latter, with a delay of what can be several hundred microseconds or more between. This observed behaviour is also evidenced by the Chromium code for Windows and POSIX implementations, where it can be seen that they do indeed do things in a step-wise manner.

Such discrete sequencing and consequential inter-signal delays (which are not an inconsequential amount of time!) can sometimes lead to unintended behaviour from a connected serial device if not taken into account.

There is also the fact that such setSignals() behaviour is in juxtaposition to the behaviour of getSignals(), for which the specification does imply that the state of all relevant signals be captured synchronously, and which current implementations actually do.

When discussing how new setSignals() states are applied, the specification currently says:

Perform the following steps in parallel:

However, I understand that the "in parallel" statement refers only to how events occur within the browser itself, rather than the way the following steps occur. Is this correct? That, together with the use of the word "steps" and a numerical listing, seems to imply that the specification wants the states of each signal to be toggled in a specifically linear fashion - each as a discrete change, one after the other.

So, a question: is that the actual specific intention of the API specification for implementations of setSignals()?

If it is, I am wondering whether it is prudent to recommend implementers document how setSignals() behaves with regard to synchronicity (or lack thereof) for changes to multiple signal states.

basilhussain avatar May 26 '25 21:05 basilhussain

I'll admit that I did not consider the specific expected behavior when authoring these steps. Without looking into the details, I would've said that the intention was for all of the specified signal changes to happen atomically. However the design of the POSIX and Windows APIs does not permit this (POSIX almost does) and so I think the best option is to define the order in which the signals are set, so that a developer who requires them to be set in a different order can do so with multiple setSignals() calls instead.

Out of this, I think there is therefore an implementation bug in Chromium on POSIX platforms, where the set/clear operations for DTR and RTS should not be merged so that they can be applied in the same explicit order they are on Windows.

Does that resolve this issue?

reillyeon avatar May 27 '25 16:05 reillyeon

However the design of the POSIX and Windows APIs does not permit this (POSIX almost does)

Ah, that's a shame. A cursory glance at the Windows API documentation for EscapeCommFunction() might give the impression one could, but the dwFunc argument values are not actually a bitmask, so can't be combined. There doesn't appear to be any other alternative API function either - not even raw IOCTLs (DTR/RTS set/clear are each separate control codes). 🙁

Does that resolve this issue?

Yes, I think so. Thank you for clarifying.

However, I think there could be an improvement on the current lack of detail about this aspect of setSignals() behaviour from all the main 'canonical' sources of documentation about the Web Serial API. For instance, MDN or Chrome Developer docs give no clue that signal states will be applied in a non-atomic, fixed sequence. I don't know whether the standards group has any influence over that.

Out of this, I think there is therefore an implementation bug in Chromium on POSIX platforms, where the set/clear operations for DTR and RTS should not be merged so that they can be applied in the same explicit order they are on Windows.

Oh, yes, you're right! I didn't look at it that closely before, but indeed - the code performs all set operations in one ioctl() call, and then all clear operations. I agree, this isn't consistent with the specification, and is a divergence of behaviour between platforms.

Is it worth me creating a new issue for this on the Chromium bug tracker?

basilhussain avatar May 27 '25 18:05 basilhussain

Yes, please file a Chromium issue to track making the behavior consistent between platforms. Then let's use this issue to track adding a note to the specification clarifying that the specified ordering is important.

reillyeon avatar May 27 '25 19:05 reillyeon

I have created issue 420689824 on the Chromium tracker..

basilhussain avatar May 27 '25 21:05 basilhussain