Skip to content

Fix nsdata fails to access contents of url #1499

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

Conversation

tid-kijyun
Copy link
Contributor

NSData (contentsOf :) was always initialized with length 0.
Also, Testing NSData (contentsOf :) on a test HTTP server(_HTTPServer) will cause deadlock, so I changed it to work on sub thread.

@spevans
Copy link
Contributor

spevans commented Apr 2, 2018

@swift-ci please test

@@ -207,7 +207,7 @@ class _HTTPServer {
deadlineTime = .now()
}

DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
DispatchQueue.global().asyncAfter(deadline: deadlineTime) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we split up the data fix itself from the change to the URLSession test code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, we can't. Without this change, deadlock will occur in testing this PR. However If you can merge split PRs in order, I should be able to do that.
Would you like to split this?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it should be merged as one PR as the HTTPServer.swift change is required for the test case to work.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think there is anything specific to HTTPServer about the change to NSData. How is it using NSData that triggers this bug?

Copy link
Contributor

@spevans spevans Apr 2, 2018

Choose a reason for hiding this comment

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

If the test case that was added (test_contentsOfURL) is calling NSData(contentsOf: url) and that is running on the main thread then won't the HTTP server have to run on another thread to service the request, or am I mis-understanding how DispatchQueue works? NSData doesn't trigger this bug, its just needed for the unit test.

Copy link
Contributor Author

@tid-kijyun tid-kijyun Apr 2, 2018

Choose a reason for hiding this comment

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

This is a code that reproduces this bug.

import Foundation

if let data = NSData(contentsOf: URL(string: "https://swift.org")!) {
    print(data.length) // 0
}

EDIT
As you says, changes to the HTTP server are necessary only for testing.
I add some explanations just in case we need it.

First, NSData(contentsOf:) uses URLSession.

https://github.com/apple/swift-corelibs-foundation/blob/2ba2086405c864e0c8bdb223209cf9a87e74a1d2/Foundation/NSData.swift#L207

Then, NSData(contentsOf:) uses NSCondition wait().
https://github.com/apple/swift-corelibs-foundation/blob/2ba2086405c864e0c8bdb223209cf9a87e74a1d2/Foundation/NSData.swift#L217
While the main thread is blocking with NSCondition wait(), The following test HTTP server code enqueued into the main thread queue is not executed.

https://github.com/apple/swift-corelibs-foundation/blob/2ba2086405c864e0c8bdb223209cf9a87e74a1d2/TestFoundation/HTTPServer.swift#L211-L214

Finally, Since there is no response from test HTTP server, deadlock will occur because the following code to resolve NSData's wait is not executed.

https://github.com/apple/swift-corelibs-foundation/blob/2ba2086405c864e0c8bdb223209cf9a87e74a1d2/Foundation/NSData.swift#L214

So, we need to change the HTTP server for testing.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, thanks for the additional info.

@millenomi
Copy link
Contributor

It makes sense to me that in the case the same thread is responding to the HTTP request initiated by NSData as the one that is blocked executing NSData(contentsOf: URL), then the test code should move its serving to a different thread.

@millenomi
Copy link
Contributor

@swift-ci please test and merge

@swift-ci swift-ci merged commit c946737 into swiftlang:master Apr 4, 2018
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.

5 participants