Main process exited, how to log ?
Added by Pedro Vicente over 1 year ago
Running a WT app app on systemd exits with this error message
The error happens randomly without any user interface action about 10 minutes after the service is started (successfully)
Jul 10 02:56:56 nostro.net nostro_web[77374]: [2023-Jul-10 02:56:56.666] 77374 [/ 8dZuW2KI0qj9uU1d] [info] "WebController: timeout: expiri>
Jul 10 02:56:56 nostro.net systemd[1]: wt.root.ssl.service: Main process exited, code=killed, status=11/SEGV
Jul 10 02:56:56 nostro.net systemd[1]: wt.root.ssl.service: Failed with result 'signal'.
Any suggestion of where to put some debugging messages ?
the refs
https://www.webtoolkit.eu/wt/doc/reference/html/overview.html#config_general
say that logs can be set with 'log-file' on the XML config file
and
--accesslog arg access log file (defaults to stdout),
at command line.
are these 2 the same log output?
Replies (6)
RE: Main process exited, how to log ? - Added by Pedro Vicente over 1 year ago
not sure if this output is relevant ?
127.0.0.1 - - [2023-Jul-10 01:56:58.043] " HTTP/-1.-1" 400 89
127.0.0.1 - - [2023-Jul-10 01:57:00.077] " HTTP/-1.-1" 400 89
127.0.0.1 - - [2023-Jul-10 01:57:02.090] " HTTP/-1.-1" 400 89
RE: Main process exited, how to log ? - Added by Pedro Vicente over 1 year ago
To note that the error happens right after message "WebController: timeout: expiring"
Jul 10 02:39:15 revo nostro_web[1049902]: [2023-Jul-10 02:39:15.259] 1049902 [/ 1Zjc7y1nxwF65bLc] [info] "WebController: timeout: expiring"
Jul 10 02:39:16 revo systemd[1]: wt.pvn.service: Main process exited, code=killed, status=11/SEGV
Jul 10 02:39:16 revo systemd[1]: wt.pvn.service: Failed with result 'signal'.
RE: Main process exited, how to log ? - Added by Stefan Bn over 1 year ago
I would change the timeout parameter in wt_config.xml to see if this behavior depends on the timeout (the default value is 600s / 10min - that fits to your timing).
The return status in your logs status=11/SEGV
indicates a segmentation fault, a bug in your code. When this always happens after the timeout then it means a particular session is automatically shut down by Wt. I would check all the destructors and if all the allocated memory in your app is released accordingly.
Do you have the chance to let your app just run in a debugger and wait/and see what happens at those timepoints? Ideally the debugger should point to where the issue is.
For debugging purposes, somewhere in your code you could also implement a user/timer-triggered call to void Wt::WApplication::quit()
, just to see if your app shuts down gracefully.
Best,
Stefan
RE: Main process exited, how to log ? - Added by Pedro Vicente over 1 year ago
Thanks, it was indeed the destructor
~ContainerHome()
{
auto app = dynamic_cast<NostroApplication*>(Wt::WApplication::instance());
app->pubkey = m_edit_pubkey->text().toUTF8();
}
So, I have 2 main containers in 2 different HTML "pages" and they both share a variable stored in the main WApplication
I did not recall that the WApplication instance is destroyed every "timeout" , is that the case?
In this case , that variable must be a global variable then
RE: Main process exited, how to log ? - Added by Pedro Vicente over 1 year ago
global variables are a bad practice
One way to avoid this in Wt is to define a inherited class from Wt::WServer
and define variables in it.
Would there be any other preferred way to accomplish this?
int main(int argc, char** argv)
{
Wt::WServer server(argc, argv);
server.addEntryPoint(Wt::EntryPointType::Application, create_application);
server.run();
}
RE: Main process exited, how to log ? - Added by Matthias Van Ceulebroeck over 1 year ago
I did not recall that the WApplication instance is destroyed every "timeout" , is that the case?
A WApplication essentially is a session specific instance. Each user that connects to an end-point, will instantiate a session. This each has its own WApplication.
Would there be any other preferred way to accomplish this?
My preferred way would be to define a unique pointer to the resource that functions as a singleton, and ensure that this exists whenever necessary. As an example:
class InstanceClass final
{
InstanceClass()
{
// Do construction
instance_ = this;
}
~InstanceClass()
{
instance_ = nullptr;
}
// Presents copy-construction
InstanceClass(const InstanceClass&) = delete;
// Presents assignment
InstanceClass& operator=(const InstanceClass&) = delete;
// Presents copy-construction (rvalue)
InstanceClass(InstanceClass&&) = delete;
// Presents assignment (rvalue)
InstanceClass& operator=(InstanceClass&&) = delete;
static const InstanceClass* instance() { return instance_; }
private:
static InstanceClass* instance_ = nullptr;
}
Then you can define in your main function:
int main(int argc, char** argv)
{
std::make_unique<InstanceClass> instanceClass = std::make_unique<InstanceClass>();
Wt::WServer server(argc, argv);
server.addEntryPoint(Wt::EntryPointType::Application, create_application);
server.run();
}
You then have access to InstanceClass::instance()
in every class where it is included.