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

Apple Network Framework Socket Changes #662

Open
wants to merge 223 commits into
base: grand_dispatch_queue
Choose a base branch
from

Conversation

sbSteveK
Copy link
Contributor

Apple Network Framework socket integration

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

new_nw_socket->connection_setup = true;

// Setup socket state to start read/write operations.
s_set_socket_state(new_nw_socket, new_socket, CONNECTED_READ | CONNECTED_WRITE);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unsure if it's necessary but we are not holding the synced data lock at the point this is called.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looking into it, We didn't lock here as we are in initializing process, no other process will touch the socket state. Updated the comment to explain it.

return;
}

struct aws_socket *aws_server_bootstrap_new_socket_listener_async(
Copy link
Contributor Author

@sbSteveK sbSteveK Mar 5, 2025

Choose a reason for hiding this comment

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

Trivial: Apart from an acquire on the server_connection_args, this is identical to the non async function. Is there any way to combine the two and perform the acquire conditionally? Or is it possible to have the acquire also happen on non-async and release? Seems like a lot of duplicated code.

Copy link
Contributor

Choose a reason for hiding this comment

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

Eventually, I removed the aws_server_bootstrap_new_socket_listener_async. Now we have a setup_callback in aws_server_socket_channel_bootstrap_options. If setup_callback is set, it will asynchronously invoke the setup_callback when the listener is ready for use.

@xiazhvera
Copy link
Contributor

The main changes since last code review:

  1. Improve the locks. Now the socket has 2 locks, (a) lock for base_socket (to avoid bad access after aws_socket_cleanup() is called) (b) lock for synced_data including socket_state and read_scheduled.
  2. Remove aws_server_bootstrap_new_socket_listener_async , now aws_server_bootstrap_new_socket_listener will asynchronously invoke the setup_callback when the listener is ready for use, if setup_callback is set.

@@ -1135,21 +1135,56 @@ static void s_socket_accept_event(
socket->io_handle.data.fd);
}

struct on_start_accept_result_args {
Copy link
Contributor

Choose a reason for hiding this comment

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

Unsure if it's worth de-duping this across posix/windows.

Copy link
Contributor

Choose a reason for hiding this comment

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

Moved it to the private header, I'm not sure if that's better either though 🤔

@@ -847,6 +847,8 @@ static void s_process_connection_result_task(struct aws_task *task, void *arg, e
struct nw_socket_scheduled_task_args *task_args = arg;
struct nw_socket *nw_socket = task_args->nw_socket;

AWS_LOGF_TRACE(AWS_LS_IO_SOCKET, "id=%p: start to process connection result task.", (void *)nw_socket);
Copy link
Contributor

Choose a reason for hiding this comment

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

Connection/listener state changes would be better as debug I think

Copy link
Contributor

Choose a reason for hiding this comment

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

Updated the state_change log to debug. For this specific line, since the function is invoking the connection result callback, I think trace would be a good to track for this callback.

new_socket->remote_endpoint.port = port;
}
if (hostname != NULL) {
size_t address_strlen;
Copy link
Contributor

Choose a reason for hiding this comment

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

We almost never want to use libc memory/string functions directly. Let's just use aws_byte_cursor_from_c_str and make a local aws_byte_buf that refers to the memory and use an appropriate copy function.

if (nw_socket->on_accept_started_fn) {
nw_socket->on_accept_started_fn(aws_socket, crt_error_code, nw_socket->listen_accept_started_user_data);
}
s_unlock_base_socket(nw_socket);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any chance that something in the accept started callback could invoke something that tries to lock the socket base?

Copy link
Contributor

Choose a reason for hiding this comment

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

The base socket is only modified(write) at two places:
(1) socket creation/init : The lock is just inited, and would not hold at this time.
(2) aws_socket_cleanup(): This is where the base socket get nulled out. We only lock the base socket if the function is not on the event loop to avoid dead lock. Use this callback as an example, if we call aws_socket_cleanup() in on_accept_started_fn, as it is on the event loop, we will not lock the base socket here.

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