Project

General

Profile

Segfault in Wt::WWebWidget::canOptimizeUpdates()

Added by John Robertson over 2 years ago

This issue was addressed in the Help forum 7 years ago, but I recently ran into it when updating widgets from the context of a custom WResource::handleRequest(). As suggested in the old discussion, I tried WResource::setTakesUpdateLock(true), but to no avail. The solution which worked was using WServer::post(), which is rather inconvenient.

I would like to understand what is going on, and why WServer::post() works when WResource::setTakesUpdateLock(true) does not. Specifically, what is going on with the thread model? In the case of concurrent HTTP requests, are several threads running through the session simultaneously? Are Wt programmers expected to write thread-safe code from within all HTTP request initiated contexts coming from the Wt library? In the examples provided I have not run across such thread-safe code.

Any suggestions are greatly appreciated!


Replies (5)

RE: Segfault in Wt::WWebWidget::canOptimizeUpdates() - Added by Roel Standaert over 2 years ago

If the WResource actually belongs to a WApplication and it is set to take the update lock, then it should normally do so. I'd need some more details, maybe a code sample, to know a bit better why it's not working for you, though. If you can use post() that's not a bad idea, though, I think that might be preferable.

RE: Segfault in Wt::WWebWidget::canOptimizeUpdates() - Added by John Robertson over 2 years ago

My WResource is associated with a subclass of WContainerWidget only through a shared_ptr member of the WContainer subclass. In the WResource::handleRequest() function I am emit()'ing a signal which causes widgets belonging to the same WContainerWidget subclass to get modified.

Following a modification of the WResource::handleRequest() to include:

WApplication::UpdateLock lck(WApplication::instance());

Now running the application produces:

Thread 5 "webcms" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffeddff700 (LWP 29006)]
Wt::WApplication::UpdateLock::UpdateLock (this=0x7fffedde5970, app=0x0) at /home/jdr/Clients/HowardCo/wt-4.2.2/src/Wt/WApplication.C:1443
1443      std::shared_ptr<WebSession> appSession = app->weakSession_.lock();

--- and this ---

Thread 6 "webcms" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffed5fe700 (LWP 29323)]
__memmove_avx_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:249
249     ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: No such file or directory.

When I instance Wt::WApplication::UpdateLock, no exceptions get thrown. Can I assume I have the session's "lock"?

The program I am writing is large and complex, and all but this part works correctly. I have debugged many multi-threaded programs before, and I know how difficult it can be to create a simple example which produces the same segfault because the threads aren't in the same place at the same time anymore. It would probably be more productive for me to dive into the Wt source code, but I was hoping to avoid that time expenditure.

RE: Segfault in Wt::WWebWidget::canOptimizeUpdates() - Added by Roel Standaert over 2 years ago

You say:

When I instance Wt::WApplication::UpdateLock, no exceptions get thrown.

But creating the UpdateLock instance is exactly what causes a segfault?

As you can see app is 0x0 there. There is no current WApplication in that context.

There's a difference between static resources that get added to the WServer with addResource and resources that are created and exposed from inside of the event loop (so when you have the application lock) by getting their url() or using a WLink associated with that resource as the target of a WAnchor, for example.

You can't use setTakesUpdateLock(true) with static resources, which is maybe what you're trying to do? You'll have to use post() or take an UpdateLock, but you'll need to make sure that you have an instance of WApplication to post to or take the lock on.

RE: Segfault in Wt::WWebWidget::canOptimizeUpdates() - Added by John Robertson over 2 years ago

Creating UpdateLock causes no problem - segfault occurs after the lock is created, and a signal is emit()'d to modify widgets.

My WResource is exposed using a WLink through a WAnchor. When the user clicks on the WAnchor, WResource::handleRequest() gets called.

I am able to succeed only when I employ both WResource::setTakesUpdateLock(true) and WServer::instance()->post().

Here is where I am confused, because this is the code which calls WServer::instance()->post()

void // static
OpsMon::
S_ss_finished(int status)
/***********************************************************************************
 * Post a function to this instance of OpsMon.
 */
{
   /* Get our application instance */
   auto app= static_cast<Cms_app*>(WApplication::instance());

   std::unique_lock<std::recursive_mutex> lock(S.update.mtx);

   auto rslt= S.update.map.find(app->sessionId());
   if(rslt != S.update.map.end())
      WServer::instance()->post(app->sessionId(), std::bind(&OpsMon::ss_finished, rslt->second, status));

}

As you can see WApplication::sessionId() is succeeding since the map search is successful. I fear the meaningful accomplishment here is merely changing the timing of my thread.

RE: Segfault in Wt::WWebWidget::canOptimizeUpdates() - Added by John Robertson over 2 years ago

Just to be clear, the code snippet above succeeds as long as WResource::setTakesUpdateLock(true) has been set.

    (1-5/5)