From 0f5d1edcd81e6d8dec97f32b8e196c933faa2f39 Mon Sep 17 00:00:00 2001 From: Damian Jarek Date: Mon, 15 Jul 2019 21:27:29 +0200 Subject: [PATCH] Fix data race in websocket examples When using `websocket::stream`, the user has to take care to initiate async operations within the associated strand. Signed-off-by: Damian Jarek --- .../async-ssl/websocket_server_async_ssl.cpp | 19 +++++++++++++++++-- .../server/async/websocket_server_async.cpp | 18 ++++++++++++++++-- .../websocket_server_stackless_ssl.cpp | 11 ++++++++++- .../stackless/websocket_server_stackless.cpp | 11 ++++++++++- 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp b/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp index fdc57aed..b79abbbf 100644 --- a/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp +++ b/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -59,14 +60,28 @@ public: { } - // Start the asynchronous operation + // Get on the correct executor void run() + { + // We need to be executing within a strand to perform async operations + // on the I/O objects in this session. Although not strictly necessary + // for single-threaded contexts, this example code is written to be + // thread-safe by default. + net::dispatch(ws_.get_executor(), + beast::bind_front_handler( + &session::on_run, + shared_from_this())); + } + + // Start the asynchronous operation + void + on_run() { // Set the timeout. beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30)); - // Perform the SSL handshake + // Perform the SSL handshake ws_.next_layer().async_handshake( ssl::stream_base::server, beast::bind_front_handler( diff --git a/example/websocket/server/async/websocket_server_async.cpp b/example/websocket/server/async/websocket_server_async.cpp index ff82e6c7..4b957086 100644 --- a/example/websocket/server/async/websocket_server_async.cpp +++ b/example/websocket/server/async/websocket_server_async.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -54,9 +55,23 @@ public: { } - // Start the asynchronous operation + // Get on the correct executor void run() + { + // We need to be executing within a strand to perform async operations + // on the I/O objects in this session. Although not strictly necessary + // for single-threaded contexts, this example code is written to be + // thread-safe by default. + net::dispatch(ws_.get_executor(), + beast::bind_front_handler( + &session::on_run, + shared_from_this())); + } + + // Start the asynchronous operation + void + on_run() { // Set suggested timeout settings for the websocket ws_.set_option( @@ -71,7 +86,6 @@ public: std::string(BOOST_BEAST_VERSION_STRING) + " websocket-server-async"); })); - // Accept the websocket handshake ws_.async_accept( beast::bind_front_handler( diff --git a/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp b/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp index 88073054..c6eaec60 100644 --- a/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp +++ b/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -65,7 +66,15 @@ public: void run() { - loop({}, 0); + // We need to be executing within a strand to perform async operations + // on the I/O objects in this session. Although not strictly necessary + // for single-threaded contexts, this example code is written to be + // thread-safe by default. + net::dispatch(ws_.get_executor(), + beast::bind_front_handler(&session::loop, + shared_from_this(), + beast::error_code{}, + 0)); } #include diff --git a/example/websocket/server/stackless/websocket_server_stackless.cpp b/example/websocket/server/stackless/websocket_server_stackless.cpp index ab44b0ee..c57fe289 100644 --- a/example/websocket/server/stackless/websocket_server_stackless.cpp +++ b/example/websocket/server/stackless/websocket_server_stackless.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -61,7 +62,15 @@ public: void run() { - loop({}, 0); + // We need to be executing within a strand to perform async operations + // on the I/O objects in this session. Although not strictly necessary + // for single-threaded contexts, this example code is written to be + // thread-safe by default. + net::dispatch(ws_.get_executor(), + beast::bind_front_handler(&session::loop, + shared_from_this(), + beast::error_code{}, + 0)); } #include