- now the mess with threads has gone away
- we have a class BaseThread -- this is a base class -- we can inherit from it when creating a new thread - others treads are correctly stopped (when signal comes) -- pthread_join - we have a special thread only for signals git-svn-id: svn://ttmath.org/publicrep/winix/trunk@685 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
164
core/app.cpp
164
core/app.cpp
@@ -11,6 +11,10 @@
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <cstdio>
|
||||
#include <fetch.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "app.h"
|
||||
#include "plugin.h"
|
||||
@@ -23,7 +27,6 @@
|
||||
|
||||
App::App()
|
||||
{
|
||||
was_stop_signal = false;
|
||||
stdout_is_closed = false;
|
||||
last_sessions_save = std::time(0);
|
||||
fcgi_socket = -1;
|
||||
@@ -45,18 +48,11 @@ App::App()
|
||||
functions.SetDb(&db);
|
||||
functions.SetSystem(&system);
|
||||
functions.SetTemplates(&templates);
|
||||
functions.SetNotify(¬ify);
|
||||
|
||||
system.SetConfig(&config);
|
||||
system.SetRequest(&request);
|
||||
system.SetDb(&db);
|
||||
|
||||
templates_notify.SetConfig(&config);
|
||||
|
||||
notify.SetRequest(&request);
|
||||
notify.SetConfig(&config);
|
||||
notify.SetSystem(&system);
|
||||
notify.SetTemplatesNotify(&templates_notify);
|
||||
system.SetSynchro(&synchro);
|
||||
|
||||
templates.SetConfig(&config);
|
||||
templates.SetRequest(&request);
|
||||
@@ -137,23 +133,15 @@ bool App::Init()
|
||||
system.Init();
|
||||
functions.Init();
|
||||
|
||||
// !! teraz mamy dwa katalogi z templetami
|
||||
// !! o co chodzilo?
|
||||
if( !notify.Init() )
|
||||
return false; // !! dodac logsave do logow
|
||||
|
||||
// call this after system.Init() (mount points identificators should be created)
|
||||
templates_notify.SetMountTypes( system.mounts.MountTypeCms(),
|
||||
system.mounts.MountTypeThread(),
|
||||
2 ); // !! chwilowo
|
||||
//system.mounts.MountTypeTicket() );
|
||||
|
||||
|
||||
// init templates after functions are created
|
||||
templates.CreateFunctions(); // create functions first (functions will be cached by patterns)
|
||||
templates.ReadIndexFileNames();
|
||||
templates.ReadTemplates();
|
||||
|
||||
// init notify after templates (it uses locales from templates)
|
||||
|
||||
system.notify.ReadTemplates();
|
||||
|
||||
session_manager.LoadSessions();
|
||||
|
||||
plugin.Call(WINIX_PLUGIN_INIT);
|
||||
@@ -228,7 +216,6 @@ void App::ProcessRequestThrow()
|
||||
}
|
||||
|
||||
SendAnswer();
|
||||
notify.ItemChanged(request.notify_code);
|
||||
|
||||
// it's better to remove sessions at the end of a request
|
||||
// as it can take a little time
|
||||
@@ -240,7 +227,19 @@ void App::ProcessRequest()
|
||||
{
|
||||
try
|
||||
{
|
||||
system.load_avg.StartRequest();
|
||||
log << log2 << config.log_delimiter << logend;
|
||||
|
||||
ProcessRequestThrow();
|
||||
|
||||
SaveSessionsIfNeeded();
|
||||
|
||||
if( request.function )
|
||||
request.function->Clear();
|
||||
|
||||
request.Clear();
|
||||
system.load_avg.StopRequest();
|
||||
log << logsave;
|
||||
}
|
||||
catch(const std::exception & e)
|
||||
{
|
||||
@@ -259,27 +258,14 @@ void App::ProcessRequest()
|
||||
|
||||
void App::Start()
|
||||
{
|
||||
while( !was_stop_signal && FCGX_Accept_r(&fcgi_request) == 0 )
|
||||
while( !synchro.was_stop_signal && FCGX_Accept_r(&fcgi_request) == 0 )
|
||||
{
|
||||
if( was_stop_signal )
|
||||
break;
|
||||
Lock();
|
||||
|
||||
// !! tu bedzie lock.WorkStart()
|
||||
if( !synchro.was_stop_signal )
|
||||
ProcessRequest();
|
||||
|
||||
system.load_avg.StartRequest();
|
||||
log << log2 << config.log_delimiter << logend;
|
||||
|
||||
ProcessRequest();
|
||||
SaveSessionsIfNeeded();
|
||||
|
||||
if( request.function )
|
||||
request.function->Clear();
|
||||
|
||||
request.Clear();
|
||||
system.load_avg.StopRequest();
|
||||
log << logsave;
|
||||
|
||||
// !! tu bedzie lock.WorkStop();
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -974,8 +960,102 @@ return true;
|
||||
}
|
||||
|
||||
|
||||
void App::WasStopSignal()
|
||||
// this method is called from a signal routine
|
||||
void App::SetStopSignal()
|
||||
{
|
||||
was_stop_signal = true;
|
||||
synchro.was_stop_signal = true;
|
||||
}
|
||||
|
||||
|
||||
bool App::WasStopSignal()
|
||||
{
|
||||
return synchro.was_stop_signal;
|
||||
}
|
||||
|
||||
|
||||
bool App::Lock()
|
||||
{
|
||||
return synchro.Lock();
|
||||
}
|
||||
|
||||
|
||||
void App::Unlock()
|
||||
{
|
||||
synchro.Unlock();
|
||||
}
|
||||
|
||||
|
||||
void App::WaitForThreads()
|
||||
{
|
||||
// special thread hangs on fetchStatURL -- I don't know why
|
||||
// but it doesn't matter, don't use pthread_join on it
|
||||
//pthread_join(signal_thread, 0);
|
||||
|
||||
system.notify.WaitForThread();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void App::FetchPageOnExit()
|
||||
{
|
||||
// stupid trick to break FCGX_Accept_r() function
|
||||
// even with FCGX_InitRequest(..., ..., FCGI_FAIL_ACCEPT_ON_INTR) the FCGX_Accept_r
|
||||
// doesn't want to break on a signal
|
||||
// so we request one page from the server for exiting from FCGX_Accept_r
|
||||
|
||||
url_stat url;
|
||||
fetchStatURL(url_to_fetch_on_exit.c_str(), &url, "");
|
||||
}
|
||||
|
||||
|
||||
void * App::SpecialThreadForSignals(void * app_object)
|
||||
{
|
||||
sigset_t set;
|
||||
|
||||
App * app = reinterpret_cast<App*>(app_object);
|
||||
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGTERM);
|
||||
sigaddset(&set, SIGINT);
|
||||
|
||||
// waiting for SIGTERM or SIGINT
|
||||
sigwait(&set, 0);
|
||||
|
||||
app->Lock();
|
||||
app->synchro.was_stop_signal = true;
|
||||
FCGX_ShutdownPending();
|
||||
Ezc::WideToUTF8(app->config.base_url, app->url_to_fetch_on_exit);
|
||||
app->system.notify.SendSignalToThread();
|
||||
app->Unlock();
|
||||
|
||||
// this thread will hang on this method
|
||||
// but will be terminated when the main thread exits
|
||||
app->FetchPageOnExit();
|
||||
|
||||
pthread_exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void App::StartThreads()
|
||||
{
|
||||
sigset_t set;
|
||||
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGTERM);
|
||||
sigaddset(&set, SIGINT);
|
||||
|
||||
// blocking SIGTERM and SIGINT
|
||||
// new threads will have the signals blocked too
|
||||
pthread_sigmask(SIG_BLOCK, &set, 0);
|
||||
|
||||
// special thread only for signals
|
||||
pthread_create(&signal_thread, 0, SpecialThreadForSignals, this);
|
||||
|
||||
// thread for notifications
|
||||
system.notify.StartThread();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user