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

Create socket with provided executor #909

Merged
merged 11 commits into from
Oct 8, 2024
Merged

Create socket with provided executor #909

merged 11 commits into from
Oct 8, 2024

Conversation

heifner
Copy link
Member

@heifner heifner commented Oct 8, 2024

Modify fc::create_listener to take a lambda that provides the executor (often a strand) for the socket that is created. This makes sure the socket is associated with the desired executor.

I don't see how this helps: #816 (comment) Maybe I'm missing something. If this doesn't help that issue, then seems like this should target main and not 1.0.3. <= Changed target to main.

Resolves #819

@heifner heifner added the OCI Work exclusive to OCI team label Oct 8, 2024
@heifner heifner linked an issue Oct 8, 2024 that may be closed by this pull request
fc::create_listener<Protocol>(thread_pool.get_executor(), _log, accept_timeout, address, "",
[this](const auto&) { return boost::asio::make_strand(thread_pool.get_executor()); },
[this](Protocol::socket&& socket) {
boost::asio::post(app().get_io_service(), [this, socket{std::move(socket)}]() mutable {
Copy link
Member

Choose a reason for hiding this comment

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

Just for code conciseness, can we go back to placing the listener on main thread to avoid this post() entirely?

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually that doesn't work: https://github.com/AntelopeIO/spring/actions/runs/11238499086
We capture the this and we need the listener to shutdown when thread_pool.stop() is called in the plugin_shutdown. This can be cleaned up when we work: #842

Copy link
Member

Choose a reason for hiding this comment

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

We capture the this and we need the listener to shutdown when thread_pool.stop() is called in the plugin_shutdown.

I'm not immediately seeing why that's a problem. this is still alive after plugin_shutdown() completes. I think something else we're missing. Maybe the already-created strand (that is using ship's thread pool's executor) expects to touch that executor when it's destroyed when async_accept() is torn down when the main thread's io_context is destroyed which is after the plugin is destroyed and thus the thread pool's executor.

But yeah can wait to touch this further later.

@spoonincode
Copy link
Member

I think it lgtm, but what are compelling reasons to make the change in 1.0? It certainly makes asio usage more idiomatic, which is good, but I don't know if we can point to something as being fixed or defective?

@heifner
Copy link
Member Author

heifner commented Oct 8, 2024

I think it lgtm, but what are compelling reasons to make the change in 1.0? It certainly makes asio usage more idiomatic, which is good, but I don't know if we can point to something as being fixed or defective?

I completely agree. I don't think this helps #816 (comment) . I asked the same question in the PR description.

@spoonincode
Copy link
Member

I think #816 (comment) was resolved with #845

@heifner
Copy link
Member Author

heifner commented Oct 8, 2024

I think #816 (comment) was resolved with #845

Right. At least until we can get a better fix via: #842

@heifner heifner changed the base branch from release/1.0 to main October 8, 2024 15:36
@heifner heifner changed the title [1.0.3] Create socket with provided executor Create socket with provided executor Oct 8, 2024
strand( my_impl->thread_pool.get_executor() ),
socket( new tcp::socket( my_impl->thread_pool.get_executor() ) ),
strand( boost::asio::make_strand(my_impl->thread_pool.get_executor()) ),
socket( new tcp::socket( strand ) ),
Copy link
Member

Choose a reason for hiding this comment

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

Now that the socket is always being created with a strand (both here and via the listener), that should mean that all the bind_executors to the strand can be removed. Not sure you want to tackle that now or not (going in to 1.0 probably not, but going in to main maybe)

Copy link
Member Author

Choose a reason for hiding this comment

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

I left it mainly because it was targeting 1.0. At this point, maybe it would be cleaner. In many places you would have boost::asio::post(socket.get_executor(), [](){}) instead which is not really any difference I don't think.

Copy link
Member

Choose a reason for hiding this comment

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

You would have to move the timers to using the strand too (afaict not a problem) but after that it does seem like all 5 bind_executors could be removed. I am not seeing the need for boost::asio::post(socket.get_executor(), [](){}) in those same spots. Anyways, it's not something that needs to be done now just a clean up I noticed since we're constructing these more idiomaticly now.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, you were talking specifically about the bind_executor. I was thinking of the boost::asio::post(strand,.

if (ec) {
fc_wlog(logger_, "Unable to retrieve local_endpoint of acceptor, error: ${e}", ("e", ec.message()));
}
acceptor_.async_accept(socket_executor_fn_(ep),
Copy link
Member

Choose a reason for hiding this comment

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

What is the purpose for the changes here and for passing the local endpoint as a parameter to the socket_executor_fn_? (this local endpoint parameter is not used by any of ship/http/p2p)

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought it might be useful. If someone was wanting to choose which executor according to which endpoint. I'm happy to remove it since we don't have a current use-case.

@ericpassmore
Copy link
Contributor

Note:start
category: System Stability
component: Internal
summary: Refactor net library to create socket with provided executor. Improves P2P, HTTP, SHiP.
Note:end

@heifner heifner merged commit c4ba58c into main Oct 8, 2024
36 checks passed
@heifner heifner deleted the GH-819-listener-strand branch October 8, 2024 20:54
@ericpassmore ericpassmore added the bug The product is not working as was intended. label Oct 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug The product is not working as was intended. OCI Work exclusive to OCI team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

P2P, HTTP, SHiP: Change fc::create_listener to use strand
4 participants