Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data race fix #50

Merged
merged 5 commits into from
Feb 25, 2024
Merged

Data race fix #50

merged 5 commits into from
Feb 25, 2024

Conversation

SimplyKyra
Copy link
Contributor

Was getting a data race issue when I started importing images on multiple threads.

The error was NIO-ELT-0-#0 (12): Assertion failed: Attempt to send request with request ID 35 already in flight.. The code errored in SFTPClient within SendRequest on line 84 assert for self.responses.responses[requestId] == nil.

I made sure the nextRequestId was incremented on the main actor thread so we didn't get duplicate request IDs.

@Joannis
Copy link
Member

Joannis commented Feb 19, 2024

Sorry for missing this PR!

@Joannis Joannis self-requested a review February 19, 2024 22:19
self.nextRequestId &+= 1
}
return self.nextRequestId
@MainActor internal func allocateRequestId() -> UInt32 {
Copy link
Member

Choose a reason for hiding this comment

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

I think we should steer away from using @MainActor here. I'd either like another (our own) globalActor, or preferrably to wrap the value in a NIOLockedValueBox

Copy link
Member

Choose a reason for hiding this comment

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

If you're unable to make that change, I can work on it sometime later

@Joannis
Copy link
Member

Joannis commented Feb 21, 2024

Thanks for the PR! I really appreciate the contribution

@SimplyKyra
Copy link
Contributor Author

Steering away from using @MainActor makes sense. I started looking into the NIOLockedValueBox option you mentioned but realized the package used in Citadel doesn't include it. Wasn't sure what your process was to move over code from Apple's Swift-NIO and I don't have the bandwidth to go through all the steps that might be required right now. That said, in case it helps you, figured I'd drop a link to it: Sources/NIOConcurrencyHelpers/NIOLockedValueBox.swift and share the untested (as it can't find NIOLockedValueBox in scope) code I did up this morning.

    /// Access to the locked box to access the nextRequestId variable
    let requestIDAccess = AllocateRequestID()

    // Call it with: requestIDAccess.allocateRequestId()

    /// A locked box to access the nextRequestId variable so it's thread safe using NIOLockedValueBox
    final class AllocateRequestID {
        /// A monotonically increasing counter for gneerating request IDs.
        private var nextRequestId: UInt32 = 0
        let lockedValueBox: NIOLockedValueBox<UInt32>
        
        init() {
            self.lockedValueBox = NIOLockedValueBox(nextRequestId)
        }
        
        /// Returns a unique request ID for use in an SFTP message. Does _not_ register the ID for
        /// a response; that is handled by `sendRequest(_:)`.
        internal func allocateRequestId() -> UInt32 {
            return self.lockedValueBox.withLock { requestId in
                defer {
                    requestId &+= 1
                }
                return requestId
            }
        }
    }

Thanks for making Citadel open. It's been really helpful. Going to use my @MainActor fix for now so no rush fixing this if you don't have the bandwidth either :)

@Joannis Joannis merged commit e8a210a into orlandos-nl:main Feb 25, 2024
@SimplyKyra SimplyKyra deleted the data_race_fix branch February 25, 2024 18:09
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