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

multi: fix incorrect multi_easy logic #12665

Closed
wants to merge 1 commit into from
Closed

Conversation

jay
Copy link
Member

@jay jay commented Jan 9, 2024

  • Use data->multi and not data->multi_easy to refer to the active multi.

Prior to this change there were a few places that incorrectly treated data->multi_easy, if != NULL, as the easy handle's active multi.

Background:

The easy handle's active multi is always data->multi. It points to either the user-created multi (if the multi interface is used) or the internally created multi (if the easy interface is used). The internally created multi is always data->multi_easy and is retained until the easy handle is cleaned up.

If an easy handle is used with the easy interface and then the multi interface, data->multi_easy and data->multi will both exist and be different.

Closes #xxxxx


There's one other that I didn't change because I'm not sure if the multi_easy should be checked before multi:

curl/lib/connect.c

Lines 270 to 287 in 8edcfed

/* this works for an easy handle:
* - that has been used for curl_easy_perform()
* - that is associated with a multi handle, and whose connection
* was detached with CURLOPT_CONNECT_ONLY
*/
if((data->state.lastconnect_id != -1) && (data->multi_easy || data->multi)) {
struct connectdata *c;
struct connfind find;
find.id_tofind = data->state.lastconnect_id;
find.found = NULL;
Curl_conncache_foreach(data,
data->share && (data->share->specifier
& (1<< CURL_LOCK_DATA_CONNECT))?
&data->share->conn_cache:
data->multi_easy?
&data->multi_easy->conn_cache:
&data->multi->conn_cache, &find, conn_is_conn);

Some logic is used to get what should be the connection cache used by the easy handle. I notice data->state.conn_cache is not checked so I assume it's not available at that point.

Copy link
Member

@bagder bagder left a comment

Choose a reason for hiding this comment

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

👍

@bagder
Copy link
Member

bagder commented Feb 20, 2024

@jay why not merge this?

@jay jay force-pushed the multi_easy branch 2 times, most recently from d5b4dff to d506808 Compare February 21, 2024 08:28
@jay
Copy link
Member Author

jay commented Feb 21, 2024

why not merge this?

I was unsure about Curl_getconnectinfo but I think I figured it out. Please review the squashme commit.

lib/connect.c Outdated
&data->multi->conn_cache, &find, conn_is_conn);
data->multi?
&data->multi->conn_cache:
&data->multi_easy->conn_cache, &find, conn_is_conn);
Copy link
Member

Choose a reason for hiding this comment

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

Is there actually a time when &data->multi->conn_cache is the incorrect choice here?

Copy link
Member

Choose a reason for hiding this comment

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

I mean, it can hardly reach this code with data->multi being NULL, can it ?

lib/multi.c Outdated
@@ -898,7 +898,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* Remove the association between the connection and the handle */
Curl_detach_connection(data);

if(data->set.connect_only && !data->multi_easy) {
if(data->set.connect_only && (data->multi != data->multi_easy)) {
Copy link
Member

Choose a reason for hiding this comment

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

Why this change? If the easy interface is not used, the multi_easy pointer is NULL so isn't both the old and the new code achieving the same thing?

Copy link
Member Author

@jay jay Feb 23, 2024

Choose a reason for hiding this comment

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

If the easy interface is not used, the multi_easy pointer is NULL

sometimes. the rub is if an easy handle is used with the easy interface and then the multi interface. in that case they point to different multis. this pr addresses that issue by prioritizing multi over multi_easy because the former is always the in-use multi. my hang up with Curl_getconnectinfo (which is used in this logic) is, following this scenario, what happens when the easy handle is removed by the user via curl_multi_remove_handle, because that would seem to cause disconnection of connections in multi_easy and not multi. (edit: no, it disconnects the multi connections without affecting the multi_easy connections) afaict, this change fixes a bug by checking that they are different and Curl_getconnectinfo prioritizes multi over multi_easy

@bagder
Copy link
Member

bagder commented Feb 26, 2024

@jay I propose #12992 so that each easy handle only has one multi handle to relate to.

@bagder
Copy link
Member

bagder commented Feb 27, 2024

Now merged. With this, an easy handle can only ever be associated with a single multi handle.

Copy link
Member

@bagder bagder left a comment

Choose a reason for hiding this comment

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

This can now be adjusted

@bagder
Copy link
Member

bagder commented Mar 12, 2024

@jay do you want me to continue this?

I believe Curl_close() can also be simplified somewhat (when the easy handle is found to be part of a multi handle).

- Use data->multi and not data->multi_easy to refer to the active multi.

The easy handle's active multi is always data->multi.

This is a follow up to 757dfdf which changed curl so that an easy handle
used with the easy interface and then multi interface cannot have two
different multi handles associated with it at the same time
(data->multi_easy from the easy interface and data->multi from the multi
interface).

Closes #xxxxx
@jay
Copy link
Member Author

jay commented Mar 13, 2024

do you want me to continue this?

I believe Curl_close() can also be simplified somewhat (when the easy handle is found to be part of a multi handle).

I dropped the fixup commit and changed the other commit's message, if more needs to be done have at it!

@jay
Copy link
Member Author

jay commented Apr 1, 2024

@bagder can you have another look, I don't think there's anything left to add

Copy link
Member

@bagder bagder left a comment

Choose a reason for hiding this comment

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

Looks good!

@jay jay added the tidy-up label Apr 5, 2024
@jay jay closed this in bf567dd Apr 5, 2024
@jay jay deleted the multi_easy branch April 5, 2024 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

None yet

2 participants