- 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:
2010-12-02 01:02:02 +00:00
parent 08e53919e2
commit 35efed9fef
52 changed files with 2464 additions and 1825 deletions

View File

@@ -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(&notify);
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();
}