Beast: "Assertion 'ws_.wr_block_ == tok_' failed" in write.ipp, line 468, Boost 1.66

Created on 29 Jan 2018  路  7Comments  路  Source: boostorg/beast

Hi,
I am trying to establish a websocket session, that keeps a pending async_read command, while processing a queue of write requests, one async_write at a time.

I keep running into this assert even with only a single thread running the pertinent io_context. I have tried to keep all the calls to these asynchronous operations on explicit strands, but I still run into the same error.

It is, to my understanding, possible to maintain these two concurrent operations, given the correct use of strands. Still, I have been unable to make it work as I expected. I would appreciate some guidance in this issue.

This happens with Beast 144 with Boost 1.66, on Windows 10 with mingw 5.3.0 32bit.

I can reproduced the issue with the following routine:
https://gist.github.com/Pinguinha/f282e049102cec63f28053e3622166bb

Thanks in advance.

Most helpful comment

This took way longer than it should have to figure out but now we know the problem and it will be fixed in Boost 1.67.0 (and the master/develop branches here). Thanks for reporting this and thanks a ton for the helpful example program, without which I could not have tracked down the problem. If you want a cheap temporary fix, change the token class in <boost/beast/websocket/stream.hpp> to use unsigned long instead of char. I will publish a solid fix shortly.

All 7 comments

Just a note, in your function onWrite if you just always post the string to the strand, and then append to the queue or initiate a send inside the posted completion handler, you won't need a mutex. Strands already come with a mutex, you're adding another one on top of it.

I am investigating, thanks for the report.

Update: I was able to build the example program after fixing a trivial compilation error in the construction of the endpoint. I also get the assert. Nothing looks wrong with your program at first glance, but the assert means an invariant has been broken so I am continuing to study it - thanks!

@Pinguinha
Probably not the root cause, but after a 5 minute glance I noticed you might have a data race in main() in line 228:

client1->socket().async_close(boost::beast::websocket::close_code::normal, [](auto){});

Looks like the access to this socket is not protected with the strand used elsewhere in WssSession

I get the assert before the async_close ever has a chance to run but you're right, it needs a strand (implicit or explicit).

I think I've stumbled upon the same issue. I made small modifications to websocket_client_async.cpp and websocket_server_async.cpp examples which are able to trigger the assert. Please take a look:

https://gist.github.com/bostjanv/5f7d6a6867f6e7e022176494730780db
https://gist.github.com/bostjanv/7240bbd40976e35696942133da684bec

I'm using Beast from Boost 1.66 and gcc 7.2.0.

This took way longer than it should have to figure out but now we know the problem and it will be fixed in Boost 1.67.0 (and the master/develop branches here). Thanks for reporting this and thanks a ton for the helpful example program, without which I could not have tracked down the problem. If you want a cheap temporary fix, change the token class in <boost/beast/websocket/stream.hpp> to use unsigned long instead of char. I will publish a solid fix shortly.

This is good news! Thanks for taking the time and figuring it out.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

a1987zz picture a1987zz  路  6Comments

shuras109 picture shuras109  路  6Comments

clekby picture clekby  路  7Comments

vchang-akamai picture vchang-akamai  路  5Comments

monada99 picture monada99  路  5Comments