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

bytes_transferred > 0 assertion fails #1373

Closed
Bobface opened this issue Dec 17, 2018 · 22 comments
Closed

bytes_transferred > 0 assertion fails #1373

Bobface opened this issue Dec 17, 2018 · 22 comments

Comments

@Bobface
Copy link

Bobface commented Dec 17, 2018

I am basically having the exactly same problem as described here: Assertion failed: (bytes_transferred > 0).

I am using a websocket::stream<ssl::stream<tcp::socket>> to connect to a ws server. After some time (can be minutes, hours or even days) the bytes_transferred > 0 assertion fails:

#2 0x00007ffff398139a in __assert_fail_base (fmt=0x7ffff3b087d8 "%s%s%s:%u: %s%sAssertion %s' failed.\n%n", assertion=assertion@entry=0x555557004919 "bytes_transferred > 0", file=file@entry=0x5555570047a8 "/usr/local/include/boost/beast/websocket/impl/read.ipp", line=line@entry=496

I can also post the full gdb stack trace if that would help.

Are there any updates regarding this bug/problem?

Thanks in advance!

Boost Version: 1.69
Asio Version: 1.12.1
Beast Version: 186
gcc (Ubuntu 8.2.0-1ubuntu2~18.04) 8.2.0

@vinniefalco
Copy link
Member

Investigating...

@vinniefalco
Copy link
Member

Are there any updates regarding this bug/problem?

No. But I guess I can add configurable setting which will invoke the completion handler with an error instead of asserting? You could opt-in to it as a workaround.

@Bobface
Copy link
Author

Bobface commented Dec 18, 2018

Are there any updates regarding this bug/problem?

No. But I guess I can add configurable setting which will invoke the completion handler with an error instead of asserting? You could opt-in to it as a workaround.

That would be great!

@vinniefalco
Copy link
Member

We think that this is very likely a bug in Asio for not handling SSL_ERROR_ZERO_RETURN. Treating it as an EOF would be the right thing to do. I have put together a patch for Asio:
vinniefalco/boost.asio@89feb2a

If you could apply this patch, uncomment the line which logs to cerr, and adjust the line so it logs to wherever/however you log in your program, then it would be very helpful for us to know what the log output is if the problem happens again. It is possible you won't see the log line (or the assert in beast) because of the handling of SSL_ERROR_ZERO_RETURN.

@Bobface
Copy link
Author

Bobface commented Dec 19, 2018

Thank you for the update! I have also investigated a little bit. I think the error only happens when I async_close the websocket stream from inside a handler which has been scheduled with asio::post. I will try to find out more and report back.

@vinniefalco
Copy link
Member

Did you try my patch?

@Bobface
Copy link
Author

Bobface commented Dec 21, 2018

I have installed it, waiting for the error to occur now.

@vinniefalco
Copy link
Member

The suspense is killing me

@Bobface
Copy link
Author

Bobface commented Dec 22, 2018

Me too. It seems like a tough bug always disappears when you are trying to track it down .. :) I am logging stderr to a file, as soon as I get some output I will post it here.

@Bobface
Copy link
Author

Bobface commented Dec 23, 2018

The error happened now, however I only got the assert output from sterr which I posted in my question above (Assertion bytes_transferred > 0 failed). I double checked that the patch is installed correctly.

@vinniefalco
Copy link
Member

What did if(result <= 0) std::cerr << "result <= 0, ssl_error = " << ssl_error << std::endl; print?

@Bobface
Copy link
Author

Bobface commented Dec 23, 2018

It didn't print anything, I only got the assertion message from stderr.

@vinniefalco
Copy link
Member

vinniefalco commented Dec 23, 2018

Hmm, but you did uncomment this line right?

 //if(result <= 0) std::cerr << "result <= 0, ssl_error = " << ssl_error << std::endl;

vinniefalco/boost.asio@89feb2a#diff-9693888572396784daf4f0aded26ce3aR286

@Bobface
Copy link
Author

Bobface commented Dec 23, 2018

Yes I did, then I rebuilt boost and my application.

@vinniefalco
Copy link
Member

Well that makes no sense at all.. in that asio file on line 287 is the only way that the function can return with the error cleared but if there's no output it means the else was not taken...

@vinniefalco
Copy link
Member

We need more info. Please try editing that engine::perform function to log as much information as possible when *bytes_transferred==0. For example what is the value of sys_error? Apparently our understanding of the function is lacking because I would have expected there to be some kind of error. So the more information that we can gather about the variables in that function when this condition occurs, the more likely we will be able to diagnose it.

@Bobface
Copy link
Author

Bobface commented Dec 23, 2018

Dereferencing bytes_transferred resulted in segfaults, so I checked for result <= 0 which seems to be more or less the same as bytes_transferred. However this spams the output with lines like this (at least 20 per second):
pending_output_before=0 result=-1 ssl_error=2 sys_error=0 pending_output_after=203

Is there a better place where I could check for result <= 0?

@pdimov
Copy link
Member

pdimov commented Dec 23, 2018

ssl_error=2 is SSL_ERROR_WANT_READ, which should be part of normal operation, so you could just skip the output in this case and see if anything else turns up.

@Bobface
Copy link
Author

Bobface commented Dec 25, 2018

The application just crashed, this is the output:

pending_output_before=0 result=0 ssl_error=6 sys_error=0 pending_output_after=0
pending_output_before=0 result=-1 ssl_error=5 sys_error=0 pending_output_after=0

The second line was printed directly before the output. The first line seems to be older.

vinniefalco added a commit to vinniefalco/boost.asio that referenced this issue Dec 25, 2018
Fix boostorg/beast#807
Fix boostorg/beast#1373

This resolves an issue where an ssl::stream read operation
returns a successful error code but zero bytes transferred,
violating its contract.

* Treat SSL_ERROR_ZERO_RETURN as EOF

* Use the ssl category for sys_error

* On error, if sys_error is 0 (success),
  return ssl::errors::read_sys_error instead.
@vinniefalco vinniefalco reopened this Dec 25, 2018
vinniefalco added a commit to vinniefalco/boost.asio that referenced this issue Dec 25, 2018
Fix boostorg/beast#807
Fix boostorg/beast#1373

This resolves an issue where an ssl::stream read operation
returns a successful error code but zero bytes transferred,
violating its contract.

* Treat SSL_ERROR_ZERO_RETURN as EOF

* Use the ssl category for sys_error

* On error, if sys_error is 0 (success),
  return ssl::errors::read_sys_error instead.
@vinniefalco
Copy link
Member

Any update?

@Bobface
Copy link
Author

Bobface commented Jan 6, 2019

Seems to be running fine so far!

@vinniefalco
Copy link
Member

I'll go ahead and close this, the pull request to fix asio is here:
boostorg/asio#182

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

Successfully merging a pull request may close this issue.

3 participants