-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Add Client method #2016
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
Merged
Merged
Add Client method #2016
Changes from 2 commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be missing something, but I'm not sure this solves the locking problem. When
cmodifiesCheckRedirectin the future, it will hold the lock. But whoever calledClient()won't have access to the lock and can modify the sameCheckRedirectfunction without holding the lock.I was thinking this would return a shallow copy:
That way both
cand the caller can modifyCheckRedirectwithout conflict.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I don't think that is necessary. The point of the lock is to prevent two clients from attempting to overwrite the same variable at the same time (for handling redirects). A shallow copy is not necessary.
The point of solving #1859 is to use the same
http.Clientfor older versions of this repo and it can be used concurrently without the need for a shallow copy.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I was thinking of a case like this (admittedly contrived):
I thought
client.DownloadReleaseAssetandclient36.MigrationArchiveURLwould acquire different locks and then modify theCheckRedirectfunction on the samehttp.Clientinstance (the two GitHub clients share a pointer.) But I could easily be overlooking or misunderstanding something.My understanding is that the
Transportfield is the most important piece to share between GitHub clients, as this has the authentication, caching, and other persistent state. Thehttp.Clientdoesn't appear to have much state of its own.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bluekeyes - I understand what you are saying, but completely disagree. What you wrote should work fine.
According to: https://pkg.go.dev/net/http
Therefore, it is safe to use a single
http.Clientconcurrently. That is not the purpose for the mutex and is not the problem being solved by it.The purpose of the mutex is to prevent a "race condition" and is there to protect the actual variable
Client.clientitself. According to Wikipedia,Some of our methods temporarily swap out the value of
Client.clientin order to perform some cool features like following redirects to get the final values so that the users of this client library don't have to figure all that stuff out for themselves.If the mutex were not there, it would be certainly possible for two concurrent goroutines to both attempt to swap out a new temporary client by both messing with the
Client.clientvariable directly, and due to the race condition, you would have no way of knowing what value would be used or how it would end up. The mutex prevents this race condition.Therefore, I stand by my assertion that this PR should be a valid solution to #1859.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking the time to discuss this with me, @gmlewis. I hope I'm not being too difficult - I use this library a lot and really appreciate the time and effort you put into maintaining it, so I only want to help fix what I believe is a bug.
To that end, Go's race detector also indicates that the solution as currently implemented has a data race.
I think this is the source of our disagreement. Looking through the library, the two functions (1, 2) that hold
client.clientMuupdate theClient.client.CheckRedirectfield, not theClient.clientfield. If parts of the library do change theClient.clientfield, they seem to do so without holding the lock.In other words, the current code uses
clientMuto prevent concurrent modification of theCheckRedirectfield. By returning a pointer to theClient.client, external code can now modify the sameCheckRedirectfield without holding the lock (which is private to the originalClient.)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, awesome, @bluekeyes !!! Looks like I'm wrong! I'm in a meeting... I'll take a look in a bit. Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I totally stand corrected... thank you for your persistence, @bluekeyes !!! I really appreciate it.
Have you tried running the race test with your shallow copy version? If it passes the race test, then I should be able to update this PR if you agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Glad we figured things out! Using a library version that makes a shallow copy of the client passes the race detector test on my machine, so I think that will work fine (unless you or anyone else spots another issue.)