@@ -45,6 +45,69 @@ namespace ws_websocketpp {
45
45
namespace transport {
46
46
namespace asio {
47
47
48
+ /* **
49
+ * In current versions of libstdc++, the error_constants.h code associated to mingw32
50
+ * does not define certain standard enum values for `std::errc`. (In C++11 standard,
51
+ * sections 19.5.2, 19.5.3.) Asio uses these for lib::asio::errc when it is compiled
52
+ * as a stand-alone library, so because of the libstdc++ defect, code below referring
53
+ * to lib::asio::errc::operation_canceled fails to compile on mingw.
54
+ *
55
+ * This workaround detects the defect using SFINAE and returns 'false' for the check
56
+ * if operation_canceled is not defined, instead of failing to compile.
57
+ *
58
+ * If upstream patches this later by defining those enum values, then the workaround
59
+ * will stop having any effect.
60
+ *
61
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68307
62
+ */
63
+ namespace _workaround_gcc_libstdcpp_issue_68307_missing_values {
64
+ /* **
65
+ * Same as std::enable_if, but don't want to introduce dependency on <type_traits>
66
+ * since that's C++11 only
67
+ */
68
+ template <bool B, class T = void >
69
+ struct enable_if {};
70
+
71
+ template <class T >
72
+ struct enable_if <true , T> { typedef T type; };
73
+
74
+ /* **
75
+ * Metafunction to test "operation_canceled" value
76
+ */
77
+ template <typename T, typename ENABLE=void >
78
+ struct op_canceled_helper {
79
+ template <typename U>
80
+ static inline bool is_op_canceled (const U & u) { return false ; }
81
+ };
82
+
83
+ template <typename T>
84
+ struct op_canceled_helper <T, enable_if<T::operation_canceled == T::operation_canceled, void > > {
85
+ template <typename U>
86
+ static inline bool is_op_canceled (const U & u) { return u == T::operation_canceled; }
87
+ };
88
+
89
+ /* **
90
+ * This function is intended to be a drop-in replacement for
91
+ * (asio_ec == lib::asio::errc::operation_canceled)
92
+ *
93
+ * except that if lib::asio::errc::operation_canceled does not exist, it returns false,
94
+ * instead of failing to compile.
95
+ *
96
+ * When using boost and not asio standalone, then lib::asio::errc is a namespace, not an enum class.
97
+ * So the template code will fail to compile and we need to block it from being instantiated, with this
98
+ * ifdef. When using boost the standard library symbol definitions aren't relevant afaik.
99
+ */
100
+ #ifdef ASIO_STANDALONE
101
+ static inline bool is_op_canceled (const lib::asio::error_code & asio_ec) {
102
+ return op_canceled_helper<lib::asio::errc, void >::is_op_canceled (asio_ec);
103
+ }
104
+ #else
105
+ static inline bool is_op_canceled (const lib::asio::error_code & asio_ec) {
106
+ return asio_ec == lib::asio::errc::operation_canceled;
107
+ }
108
+ #endif
109
+ } // namespace _workaround
110
+
48
111
// / Asio based endpoint transport component
49
112
/* *
50
113
* transport::asio::endpoint implements an endpoint transport component using
@@ -833,7 +896,8 @@ class endpoint : public config::socket_type {
833
896
m_alog->write (log::alevel::devel, " asio::handle_accept" );
834
897
835
898
if (asio_ec) {
836
- if (asio_ec == lib::asio::errc::operation_canceled) {
899
+ // if (asio_ec == lib::asio::errc::operation_canceled) {
900
+ if (_workaround_gcc_libstdcpp_issue_68307_missing_values::is_op_canceled (asio_ec)) {
837
901
ret_ec = make_error_code (ws_websocketpp::error::operation_canceled);
838
902
} else {
839
903
log_err (log::elevel::info," asio handle_accept" ,asio_ec);
0 commit comments