-
Notifications
You must be signed in to change notification settings - Fork 90
Fixed closing of already closed http_listener. #258
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
Conversation
|
Hm, that doesn't sound good. Can you explain how But I do agree What we probably expected to happen is this... This would be handled by We could submit a test case and patch to cpprestsdk but given it's in maintenance mode, I agree it might be simpler to handle the issue in this repo, though there are several instances of But first, I'd prefer to understand the first point, how |
|
I found the implementation of close() here. So basically you are right, this bug should better be fixed in cpprest. But I'm not sure, how easy it is to provide a patch for cpprest. |
|
I quickly added microsoft/cpprestsdk#1700 and microsoft/cpprestsdk#1701. Patches for both issues should be possible. However, to avoid having to wait for that to happen, maybe we could replace instances of pplx::ranges::when_all(tasks | boost::adaptors::transformed([](pplx::task<X> task)
{
try { task.is_done(); return task; }
catch (const pplx::invalid_operation& e) { return pplx::task_from_exception<X>(e); }
})(where |
|
Thanks for adding the issues at cpprest. I'm not an cpprest expert. Could you please explain if you like to write a new function Nevertheless, I think it is a very good idea to fix the |
|
Yes, sorry, typo fixed! Those |
|
Okay thanks, now it is more clear to me. This function is then called by your code and should then only handle valid tasks, right? |
If we don't want to rely on that, we could do as I originally wrote: try { task.wait(); return task; }
catch (const pplx::invalid_operation& e) { return pplx::task_from_exception<X>(e); }
catch (...) { return task; }The possible issue that made me rewrite using
Yes, so I think the following may be sufficiently composable, leaving the job of template <typename InputRange>
pplx::task<void> when_all(InputRange&& tasks, const task_options& options = task_options())
{
return pplx::when_all(tasks.begin(), tasks.end(), options);
} |
|
Okay I agree that |
|
Yes, |
|
Okay, that's fine. I'm currently testing the code changes with a small unit test that adds some I'm not absolutely sure but I think that the created task from |
|
Sorry, I'm away from compiler right now. In my tests, In total I was expecting something like this to work... return pplx::ranges::when_all(tasks | boost::adaptors::transformed([](pplx::task<void> task)
{
try { task.is_done(); return task; }
catch (const pplx::invalid_operation& e) { return pplx::task_from_exception<void>(e); }
}).then([tasks](pplx::task<void> finally)
{
for (auto& task : tasks) details::wait_nothrow(task);
finally.wait();
});Maybe you're right and (knowing that the fix really belongs in cpprestsdk in the impl of return pplx::ranges::when_all(tasks)
.then(pplx::observe_exception<void>(tasks)); |
|
I've implemented exactly the same code but it crashes with an unhandled exception. I did my tests under Windows using Visual Studio 2017 and ccprest 2.10.18. It does not crash when I use The crash happens in the destructor of the task in Here is the call stack stored in this->_M_stackTrace: Thus, the problem seems to be that Because I would assume that the task returned from |
Moved fix into a pplx::range::when_all() function getting a filtered list of tasks. Added an unit test for pplx::range::when_all().
|
Ah, sorry, I realise the issue... Although Two possible solutions - map to |
|
@SvenKordon I've had a quick go at this... so far I've made |
|
@garethsb I looked into your code which is fine for me so far. I think, it is a good idea to have our own implementation for However, there is one thing I'm not really sure about. Maybe the patched code is not asynchronous anymore as the
I'd expect that the |
|
Do you mean the call to That is protected by the previous line: if (!pplx::empty(task)) return task;The Or have I missed something? |
|
Okay sure! Sorry, now I've got it. We check for an empty task and call Thanks a lot! I learned a lot about cpprest and boost by this. I think we can close this pull request. Okay? |
I observed a crash of the nmos-cpp library when the nmos::server is closed and the http_listeners vector contains already closed listeners.
http_listener::close() returns a default created pplx::task from cpprest (2.10.17). This leads to a crash in pplx::when_all() under Linux CentOS8.1. I did not investigate the reason for this crash further, however, default created pplx::task behave different. For example they throw on wait or get calls.
To solve this issue I propose the following fix which only adds non default created tasks to the vector.
The provided fix is tested in my application where the problem occurs when a nmos::server is closed that comprises invalid http_listeners due to wrong socket configurations, like for example an already existing port number.