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

How to compile websocketpp examples for mingw using C++11 std::thread? #478

Open
cbeck88 opened this issue Nov 12, 2015 · 6 comments
Open

Comments

@cbeck88
Copy link

cbeck88 commented Nov 12, 2015

Hi, I'm trying to compile websocketpp using stand-alone Asio transport-layer, C++11, and no boost in a cross-platform application. When I use just asio I can make simple http servers just fine, I have been using mingw's winpthread library.

When I tried to use websocketpp, I get problems because it assumes that mingw does not have std::thread, and wants boost::thread. I guess maybe some versions of mingw didn't support this and required work arounds like this, but current versions (mine from Ubuntu trusty standard i686-mingw32-w64-g++ package?) seems to have this.

I therefore have been circumventing the code in common/thread.hpp by compiling with -D_WEBSOCKETPP_CPP11_THREAD_=1 in order to override its preference for boost::thread on mingw.

However, seemingly unrelated to this I get a bizarre compilation error:

In file included from websocketpp-0.6.0/include/websocketpp/config/asio_no_tls_client.hpp:32:0,
                 from main.cpp:31:
websocketpp-0.6.0/include/websocketpp/transport/asio/endpoint.hpp: In member function ‘void websocketpp::transport::asio::endpoint<config>::handle_accept(websocketpp::transport::accept_handler, const error_code&)’:
websocketpp-0.6.0/include/websocketpp/transport/asio/endpoint.hpp:764:28: error: ‘operation_canceled’ is not a member of ‘std::errc’
             if (asio_ec == lib::asio::errc::operation_canceled) {
                            ^

I get this error when trying to build anything, in particular, the utility_client.cpp file.
Can you advise what is the proper way to build the tutorial code on mingw, if possible using asio with C++11 threads and not boost::thread?

I made a simple repo to assist in reproducing my exact problem: https://github.com/cbeck88/wspp_mingw_test

I have also posted this question on stack overflow, since I'm really not sure if it means there is a problem with my toolchain.

Thanks for your time and attention.

@zaphoyd
Copy link
Owner

zaphoyd commented Nov 12, 2015

Does it compile with regular g++ on this system?

defining _WEBSOCKETPP_CPP11_THREAD_ is an appropriate way to force the use of std::thread.

@cbeck88
Copy link
Author

cbeck88 commented Nov 12, 2015

It compiles fine with g++ and clang++ (4.8.4 and 3.6 resp.).

I was looking in my mingw system headers, at /usr/include/c++/4.8/i686-w64-mingw32/bits/error_constants.h I have some suspicious looking stuff:

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

// Most of the commented-out error codes are socket-related and could be
// replaced by Winsock WSA-prefixed equivalents.
  enum class errc
    {
//    address_family_not_supported =        EAFNOSUPPORT,
//    address_in_use =              EADDRINUSE,
//    address_not_available =           EADDRNOTAVAIL,
//    already_connected =           EISCONN,
      argument_list_too_long =          E2BIG,
      argument_out_of_domain =          EDOM,
      bad_address =                 EFAULT,
      bad_file_descriptor =             EBADF,
//    bad_message =                 EBADMSG,
      broken_pipe =                 EPIPE,
//    connection_aborted =          ECONNABORTED,
//    connection_already_in_progress =      EALREADY,
//    connection_refused =          ECONNREFUSED,
//    connection_reset =            ECONNRESET,
//    cross_device_link =           EXDEV,
//    destination_address_required =        EDESTADDRREQ,
      device_or_resource_busy =         EBUSY,
      directory_not_empty =             ENOTEMPTY,
      executable_format_error =         ENOEXEC,
      file_exists =                     EEXIST,
      file_too_large =              EFBIG,

...

//    not_a_socket =                ENOTSOCK,
//    not_a_stream =                ENOSTR,
//    not_connected =               ENOTCONN,
      not_enough_memory =           ENOMEM,
#ifdef _GLIBCXX_HAVE_ENOTSUP
      not_supported =               ENOTSUP,
#endif
//    operation_canceled =          ECANCELED,
//    operation_in_progress =           EINPROGRESS,
#ifdef _GLIBCXX_HAVE_EPERM
      operation_not_permitted =         EPERM,
#endif
//    operation_not_supported =         EOPNOTSUPP,
#ifdef _GLIBCXX_HAVE_EWOULDBLOCK
      operation_would_block =           EWOULDBLOCK,
#endif
//    owner_dead =              EOWNERDEAD,
      permission_denied =           EACCES,
//    protocol_error =              EPROTO,
//    protocol_not_supported =          EPROTONOSUPPORT,
      read_only_file_system =           EROFS,
      resource_deadlock_would_occur =       EDEADLK,
      resource_unavailable_try_again =      EAGAIN,
      result_out_of_range =             ERANGE,

So, it looks like they just commented out this definition? That sounds rather suspicious to me but maybe I'm missing something...

@zaphoyd
Copy link
Owner

zaphoyd commented Nov 12, 2015

that would explain the error. I can't think of an obvious reason to do this. perhaps the mingw dev folks might have more insight?

@cbeck88
Copy link
Author

cbeck88 commented Nov 12, 2015

Yeah, I will ask them

Edit: Posted to their issue tracker here: https://sourceforge.net/p/mingw-w64/support-requests/105/
Edit: After discussion with mingw folks, we think it is a bug in libstdc++, now reported here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68307

@cbeck88
Copy link
Author

cbeck88 commented Nov 12, 2015

Hi, so I fooled around with this some more, here is what I can report:

  • Using the default i686-w64-mingw32-g++ which is shipped with ubuntu trusty
  • Using the default wine package which is shipped with ubuntu trusty
  • Asio 1.10.6 release headers
  • websocketpp 0.6.0 release headers
  • Modifying the libstdc++ headers for mingw32 as follows:
    At the very end of the enum declaration for std::errc in the file /usr/include/c++/4.8/i686-w64-mingw32/bits/error_constants.h
    add a line for
    operation_canceled = ECANCELED, };

Then, I can compile both the utility client and the echo server using mingw g++ with std=c++11 defines -D_WEBSOCKETPP_CPP11_THREAD_=1 -DASIO_STANDALONE=1 and link flags -lpthread -lws2_32 -lmswsock, and I can also compile with g++ using just -DASIO_STANDALONE=1.

Then all of these programs work and can interoperate, i.e., the g++ compiled echo server can talk to the mingw compiled utility client running in wine, etc., and this is without any mingw boost being available.

So... modifying the libstdc++ header is not fun and I don't know if this is really "working" but at least it appears to work. Hopefully upstream can confirm this and make a patch I guess.

@cbeck88
Copy link
Author

cbeck88 commented Nov 12, 2015

It occurs to me now, the only better workaround I can think of that doesn't involve modifying system headers is, insert some code into websocket/transport/asio/endpoint.hpp which uses SFINAE to detect if the symbol lib::asio::errc::operation_canceled is defined, and if not then substitute with the <cerrno> code... I guess I might just do that in my project or something.

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

No branches or pull requests

2 participants