Bug #8202
closedwApp returns nullptr inside a WServer::postAll lambda
100%
Description
Hello,
I have this code, called from a thread outside the WIOService used by the WServer:
server.postAll([]
{
wApp->getEventXXX().emit();
wApp->triggerUpdate();
});
And it looks like wApp is nullptr.
Here is what I get in the core file:
(gdb) bt
#0 0x00039a50 in Wt::Signals::Impl::ProtoSignal<>::emit() const (this=0x4d4) at /usr/include/Wt/Signals/signals.hpp:216
#1 0x00033ee0 in Wt::Signal<>::emit() const (this=<optimized out>) at /usr/include/Wt/WSignal.h:758
#2 <lambda()>::<lambda()>::operator() (__closure=<optimized out>) at ./src/lms/main.cpp:131
#3 std::_Function_handler<void(), proxyScannerEventsToApplication(Scanner::IScanner&, Wt::WServer&)::<lambda()>::<lambda()> >::_M_invoke(const std::_Any_data &) (
__functor=...) at /usr/include/c++/8/bits/std_function.h:297
#4 0xb69ac7dc in std::function<void ()>::operator()() const (this=<optimized out>) at /usr/include/c++/8/bits/std_function.h:682
#5 Wt::WebSession::notify (this=this@entry=0xac304658, event=...) at ./src/web/WebSession.C:2214
#6 0xb69af4b0 in Wt::WebSession::externalNotify (this=this@entry=0xac304658, event=...) at ./src/Wt/WEvent.h:137
#7 0xb69af5c4 in Wt::WebSession::processQueuedEvents (this=0xac304658, handler=...) at ./src/web/WebSession.h:396
#8 0xb69af850 in Wt::WebSession::Handler::~Handler (this=0xae0fb954, __in_chrg=<optimized out>) at ./src/web/WebSession.C:1053
#9 0xb6992c80 in Wt::WebController::handleApplicationEvent (this=0x12b7210, event=...) at ./src/web/WebController.C:544
#10 0xb66b85d4 in std::function<void ()>::operator()() const (this=0xae0fb9bc) at /usr/include/c++/8/bits/std_function.h:682
#11 boost::asio::asio_handler_invoke<std::function<void ()> >(std::function<void ()>&, ...) (function=...) at /usr/include/boost/asio/handler_invoke_hook.hpp:69
#12 boost_asio_handler_invoke_helpers::invoke<std::function<void ()>, std::function<void ()> >(std::function<void ()>&, std::function<void ()>&) (context=..., function=...)
at /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:37
#13 boost::asio::detail::handler_work<std::function<void ()>, boost::asio::system_executor>::complete<std::function<void ()> >(std::function<void ()>&, std::function<void ()>&) (this=<synthetic pointer>, handler=..., function=...) at /usr/include/boost/asio/detail/handler_work.hpp:82
#14 boost::asio::detail::completion_handler<std::function<void ()> >::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned int) (owner=owner@entry=0x14601b0, base=0xae907860) at /usr/include/boost/asio/detail/completion_handler.hpp:70
#15 0xb66ba8c8 in boost::asio::detail::scheduler_operation::complete (bytes_transferred=0, ec=..., owner=0x14601b0, this=<optimized out>)
at /usr/include/boost/asio/detail/scheduler_operation.hpp:40
#16 boost::asio::detail::strand_service::do_complete (owner=owner@entry=0x14601b0, base=base@entry=0x1460ef8, ec=...)
at /usr/include/boost/asio/detail/impl/strand_service.ipp:168
#17 0xb66b4ed8 in boost::asio::detail::scheduler_operation::complete (bytes_transferred=<optimized out>, ec=..., owner=0x14601b0, this=0x1460ef8)
at /usr/include/boost/asio/detail/scheduler_operation.hpp:40
#18 boost::asio::detail::scheduler::do_run_one (ec=..., this_thread=..., lock=..., this=0x14601b0) at /usr/include/boost/asio/detail/impl/scheduler.ipp:401
#19 boost::asio::detail::scheduler::run (ec=..., this=0x14601b0) at /usr/include/boost/asio/detail/impl/scheduler.ipp:154
#20 boost::asio::io_context::run (this=<optimized out>) at /usr/include/boost/asio/impl/io_context.ipp:62
#21 Wt::WIOService::run (this=<optimized out>) at ./src/Wt/WIOService.C:180
#22 0xb631a9b0 in ?? () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#23 0xb6e0f494 in start_thread (arg=0xae0fc0e0) at pthread_create.c:486
#24 0xb6157578 in ?? () at ../sysdeps/unix/sysv/linux/arm/clone.S:73 from /lib/arm-linux-gnueabihf/libc.so.6
(gdb) p (*Wt::threadHandler_->sessionPtr_)->app_
$11 = (Wt::WApplication *) 0x0
(Source is here if you want to see more: https://github.com/epoupon/lms/blob/v3.24.0/src/lms/main.cpp#L131)
What do you think?
Updated by Korneel Dumon over 3 years ago
- Status changed from New to InProgress
- Assignee set to Korneel Dumon
This seems to happen when you close the page before it is finished loading. I can reproduce it by throttling the browser so I am quick enough to close it. Can you confirm this?
I think it has something to do with Wt's bootstrap process. If you close the page before the bootstrap request is finished, then we created a WebSession, but not yet a WApplication.
My suspicion is confirmed by the fact that the problem is gone when I enable progressive bootstrap (which renders the application on the first request).
Even if there is no wApp, the session is still cleaned up after a while. So if you just add a null-check, you should be good. I will see if I can also add it somewhere in Wt to prevent this from happening.
Updated by Emeric Poupon over 3 years ago
Korneel Dumon wrote in #note-2:
This seems to happen when you close the page before it is finished loading. I can reproduce it by throttling the browser so I am quick enough to close it. Can you confirm this?
I think it has something to do with Wt's bootstrap process. If you close the page before the bootstrap request is finished, then we created a WebSession, but not yet a WApplication.
My suspicion is confirmed by the fact that the problem is gone when I enable progressive bootstrap (which renders the application on the first request).Even if there is no wApp, the session is still cleaned up after a while. So if you just add a null-check, you should be good. I will see if I can also add it somewhere in Wt to prevent this from happening.
Hello!
Unfortunately, I don't manage to reproduce this issue :(
But a user reported he gets this 100%, not mentioning the closing step (see https://github.com/epoupon/lms/issues/126 for for more details)
Indeed I don't use the progressive bootstrap feature.
Updated by Korneel Dumon over 3 years ago
Perhaps your user always has unfortunate timing. Between the first and second request there is always a small interval where wApp is null. If you call postAll()
during this time, it will crash. The conclusion is the same, you can safely ignore these incomplete applications.
You can stretch the interval by throttling the browser, maybe you can reproduce it in this way.
Updated by Korneel Dumon over 3 years ago
- Status changed from InProgress to Implemented @Emweb
Updated by Roel Standaert over 3 years ago
- Status changed from Implemented @Emweb to Resolved
- Target version set to 4.5.1
Updated by Roel Standaert about 3 years ago
- Status changed from Resolved to Closed