Conversation
|
Thank you for this PR @VMshall! Looking at you second commit c0aa072: Might this just be an accidental check-in of some files from you working directory? In case it is, you can reset you branch to f1759e5 and update the PR by force-pushing to the branch. Please ignore build errors from our MSRV targets. The are caused by our pretty old MSRV and updated dependencies which do not consider MSRV changes semver-breaking. |
c0aa072 to
9915c59
Compare
RossSmyth
left a comment
There was a problem hiding this comment.
I'm unsure of the value of this API, I don't particularly see the point? Could you explain your motivation a bit more? From a win32 perspective I don't really see the point in carrying more data in the struct, if you open it exclusively you do so explicitly, not too much point in carrying that data along for the entire lifetime of the structure.
It would probably be more worthwhile to add an API to add os-specific opening flags like in std.
src/windows/com.rs
Outdated
| handle: handle as HANDLE, | ||
| timeout: Duration::from_millis(100), | ||
| port_name: None, | ||
| exclusive: true, // conservative default matching legacy behaviour |
There was a problem hiding this comment.
While this is legacy, this is not conservative. It should really default to false.
Plus it is possible to determine.
There was a problem hiding this comment.
Thanks for the review, Ross!
The motivation behind the exclusive option in the builder was to provide a cross-platform way to opt out of exclusive locking, as unconditionally acquiring an exclusive lock (flock) on Unix was preventing users from opening two shared TTYPorts. I agree there's no need to carry the state around for the lifetime of the struct. I will update the PR to remove the exclusive field and getter from both COMPort and TTYPort and only use it at open-time in the builder.
There was a problem hiding this comment.
While this is legacy, this is not conservative. It should really default to false.
Is it actually? Doesn't COMPort open the device file in exclusive mode as of now?
There was a problem hiding this comment.
Just because our default is exclusive doesn't mean it is conservative. You can create a COMPort from an external handle via FFI that we do not control (and I do in several projects), and at that time you have no idea how it was opened.
There was a problem hiding this comment.
I imagine there is a similar API on Linux, though I do not use this library for Linux applications much.
There was a problem hiding this comment.
Just because our default is exclusive doesn't mean it is conservative. You can create a COMPort from an external handle via FFI that we do not control (and I do in several projects), and at that time you have no idea how it was opened.
Good point. And to me this makes another case for crafting eventual support for checking exclusivity more carefully. At a first glance, this seems not be trivially possible on Window. However, we could navigate around this by returning an Option<bool> with an actual value for the case the file has been opened by us and None for port instances created from raw handles/file descriptors.
|
Thank you for continuing the discussion in the meantime @RossSmyth and @VMshall!
Could you give us a reference to that? Do you mean OS-specific flags on the builder?
I see value an adding support for allowing the user to configure file locking for a serial port. It's there, always on and I know the following two reports where this stands in the way of users who want to read and write from separate threads: #309 and #314. And of course, the demand stems from the lack of support for splitting a serial port instance into something like a read and write half for this use case. But even if the cases above are not the "right" motivation for making locking configurable, what would be your case against adding the option to the builder @RossSmyth? I'm just referring to tho builder so far. From my point, it's perfectly fine to postpone the decision on how to add this to the platform implementations. I see the point in adding support for querying the locking status @VMshall. It's there for the Posix backend so why not for Windows too? The runtime cost for carrying the flag around in the What bothers me more is that there is the presence of I would opt for adding support for configuring locking from the builder and discuss and develop the rest in an separate issue (in the context of #302). With that said, do you have a point with making locking configurable through the builder and postpone API changes to the port implementations and the serialport trait @RossSmyth? |
|
Maybe I just don't use my serial port the same way, but I do not really see any way to have the same serial port open more than once in a way that doesn't result in junk data. I guess the one issue linked it is just writing on one thread and reading on the other, which just gets buffered in the kernel so nothing can really be raced. But without enforcing that reading and writing at the API level it seems fragile to me. The runtime cost doesn't matter too much since I imagine no one opens thousands of serial ports, so doesn't really matter too much. As for os-specific APIs, I was referring to these |
|
Thanks for the review and discussion, @RossSmyth and @sirhcel i completely agree with the points raised there's no need to carry the exclusive state throughout the lifetime of the COMPort or TTYPort structs, especially since we can't reliably determine the state from raw handles anyway. I've just pushed a new commit that implements your feedback ,removed the exclusive field entirely from both COMPort and TTYPort. removed the exclusive() getter from both platforms, and removed the set_exclusive() method from TTYPort. Builder only configuration: Exclusivity is now strictly an opentime configuration handled solely by SerialPortBuilder. It evaluates the flag at the time of opening and discards it. |
|
Thank you @VMshall, I'm keen on having a look at your update but I can't find it here in the PR nor in your fork. Where did you push the changes to?
Sorry to interrupt here: Please leave the existing exclusivity flag and |
|
Thanks for the clarification! I'll restore the exclusivity flag and |
|
Thanks for the clarification, @sirhcel I've updated the PR to adhere to semantic versioning for the 4.x release line. The existing Please let me know if anything looks off. |
|
Thank you for the cleanup!
Yes, I'm wondering what's behind merging the main branch back into the PR branch? My gut instinct would have it kept it a sideline to main for rebasing. Could you please add an entry to the changelog? |
|
I merged the |
8a70eb1 to
0fb7a3b
Compare
|
Thank you for the changelog @VMshall! I refactored the commits to what I had in mind with 0fb7a3b4:
My update should have gone to a separate brach but ended up directly in this PR. I'm about to refactor the tests for locking to cover the exclusivity setting and will add them soon. |
This includes some refactoring to make the individual test cases more concise and readable.
|
Here they finally are, the tests. And it has been an interesting journey: I learned that on Windows, using a shared lock for COM ports is not supported on Windows. This explains why there was no support for configuring a locking mode on Windows available so far. This means that we need to adapt our configuration approach where Do you want to give the aforementioned refactoring a shot @VMshall? |
|
@sirhcel Yes, I'd love to give it a shot! |
Fixes #314.
Currently, the library unconditionally requests an exclusive lock when opening a serial port (
flock::lock_exclusiveon POSIX andshare_mode = 0on Windows). This prevents scenarios where two sharedTTYPortsorCOMPortsneed to be opened simultaneously (e.g., when working with pseudo-terminals).exclusive: boolfield toSerialPortBuilder, defaulting totrueto maintain backwards compatibility.pub fn exclusive(mut self, exclusive: bool) -> Selfbuilder method.src/posix/tty.rs): UpdatedTTYPort::opento checkbuilder.exclusive. Iftrue, it appliesioctl::tiocexclandflock::lock_exclusive. Iffalse, it appliesioctl::tiocnxclandflock::lock_shared.src/windows/com.rs): UpdatedCOMPort::opento checkbuilder.exclusive. Iftrue, it uses ashare_modeof0. Iffalse, it usesFILE_SHARE_READ | FILE_SHARE_WRITE.This allows users to explicitly opt-out of exclusive locking when they need shared access to a port.