stablized the signal functions in the App class

This commit is contained in:
hyung-hwan 2018-09-10 14:15:28 +00:00
parent 9764d448af
commit 1218015572
9 changed files with 65 additions and 227 deletions

View File

@ -76,7 +76,6 @@ public:
return this->setSignalSubscription (sig, SIGNAL_UNHANDLED);
}
typedef void (*SignalHandler) (int sig);
static qse_size_t _sighrs[2][QSE_NSIGS];
@ -87,7 +86,7 @@ public:
// yet, a subsequence call to subscribeToSignal() is doomed to fail too.
// These two different interfaces are mutually exclusive.
static int setSignalHandler (int sig, SignalHandler sighr);
static int unsetSignalHandler (int sig);
static int unsetSignalHandler (int sig, bool ignore = false);
int guardProcess (const qse_mchar_t* proc_name, const SignalSet& signals);
@ -108,14 +107,10 @@ private:
protected:
static int set_signal_handler_no_mutex (int sig, SignalHandler sighr);
static int unset_signal_handler_no_mutex (int sig);
static int unset_signal_handler_no_mutex (int sig, int ignore);
int set_signal_subscription_no_mutex (int sig, SignalState reqstate);
int subscribe_to_signal_no_mutex (int sig, SignalState reqstate);
void unsubscribe_from_signal_no_mutex (int sig);
void unsubscribe_from_all_signals_no_mutex ();
void on_guard_signal (int sig);
static void handle_signal (int sig);

View File

@ -43,10 +43,34 @@ static struct
sigset_t sa_mask;
int sa_flags;
} g_app_oldsi[QSE_NSIGS] = { { 0, 0 }, };
static bool g_app_sigign_on_exit = false;
class SigScopedMutexLocker
{
public:
SigScopedMutexLocker (Mutex& mutex): mutex(mutex)
{
sigset_t sigset;
::sigfillset (&sigset);
::sigprocmask (SIG_BLOCK, &sigset, &this->oldsigset);
// TODO: would this work properly if this is called within a thread?
// do i need to use pthread_sigmask() conditionally?
this->mutex.lock ();
}
~SigScopedMutexLocker ()
{
this->mutex.unlock ();
::sigprocmask (SIG_SETMASK, &this->oldsigset, QSE_NULL);
}
protected:
Mutex& mutex;
sigset_t oldsigset;
};
App::App (Mmgr* mmgr) QSE_CPP_NOEXCEPT: Mmged(mmgr), _prev_app(QSE_NULL), _next_app(QSE_NULL), _guarded_child_pid(-1)
{
ScopedMutexLocker sml(g_app_mutex);
SigScopedMutexLocker sml(g_app_mutex);
if (!g_app_top)
{
g_app_top = this;
@ -60,8 +84,11 @@ App::App (Mmgr* mmgr) QSE_CPP_NOEXCEPT: Mmged(mmgr), _prev_app(QSE_NULL), _next_
App::~App () QSE_CPP_NOEXCEPT
{
ScopedMutexLocker sml(g_app_mutex);
this->unsubscribe_from_all_signals_no_mutex ();
SigScopedMutexLocker sml(g_app_mutex);
for (int i = 0; i < QSE_NSIGS; i++)
{
this->set_signal_subscription_no_mutex (i, SIGNAL_UNHANDLED);
}
if (this->_next_app) this->_next_app->_prev_app = this->_prev_app;
if (this->_prev_app) this->_prev_app->_next_app = this->_next_app;
if (this == g_app_top)
@ -207,7 +234,7 @@ static void dispatch_siginfo (int sig, siginfo_t* si, void* ctx)
int App::setSignalHandler (int sig, SignalHandler sighr)
{
ScopedMutexLocker sml(g_app_mutex);
SigScopedMutexLocker sml(g_app_mutex);
return App::set_signal_handler_no_mutex (sig, sighr);
}
@ -222,13 +249,13 @@ int App::set_signal_handler_no_mutex (int sig, SignalHandler sighr)
if (oldsa.sa_flags & SA_SIGINFO)
{
sa.sa_sigaction = dispatch_siginfo;
sigemptyset (&sa.sa_mask);
::sigfillset (&sa.sa_mask); // block all signals while the handler is being executed
sa.sa_flags |= SA_SIGINFO;
}
else
{
sa.sa_handler = dispatch_signal;
sigemptyset (&sa.sa_mask);
::sigfillset (&sa.sa_mask);
sa.sa_flags = 0;
//sa.sa_flags |= SA_INTERUPT;
//sa.sa_flags |= SA_RESTART;
@ -244,13 +271,13 @@ int App::set_signal_handler_no_mutex (int sig, SignalHandler sighr)
return 0;
}
int App::unsetSignalHandler (int sig)
int App::unsetSignalHandler (int sig, bool ignore)
{
ScopedMutexLocker sml(g_app_mutex);
return App::unset_signal_handler_no_mutex(sig);
SigScopedMutexLocker sml(g_app_mutex);
return App::unset_signal_handler_no_mutex(sig, ignore);
}
int App::unset_signal_handler_no_mutex(int sig)
int App::unset_signal_handler_no_mutex(int sig, int ignore)
{
if (!App::_sighrs[0][sig]) return -1;
@ -258,13 +285,18 @@ int App::unset_signal_handler_no_mutex(int sig)
sa.sa_mask = g_app_oldsi[sig].sa_mask;
sa.sa_flags = g_app_oldsi[sig].sa_flags;
if (sa.sa_flags & SA_SIGINFO)
if (ignore)
{
sa.sa_handler = SIG_IGN;
sa.sa_flags &= ~SA_SIGINFO;
}
else if (sa.sa_flags & SA_SIGINFO)
{
sa.sa_sigaction = (void(*)(int,siginfo_t*,void*))App::_sighrs[1][sig];
}
else
{
sa.sa_handler = (SignalHandler)App::_sighrs[1][sig];
printf ("unset signal handler......\n");
sa.sa_handler = SIG_IGN;
}
if (::sigaction (sig, &sa, QSE_NULL) <= -1) return -1;
@ -274,10 +306,15 @@ sa.sa_handler = SIG_IGN;
return 0;
}
/*static*/ void App::handle_signal (int sig)
{
ScopedMutexLocker sml(g_app_mutex);
// Note: i use ScopedMutexLocker in the signal handler
// whereas I use SigScopedMutexLocker in other functions.
// as SigScopedMutexLock blocks all signals, this signal handler
// is not called while those other functions are holding on to
// this mutex object.
ScopedMutexLocker sml(g_app_mutex);
App* app = g_app_sig[sig];
while (app)
{
@ -311,20 +348,8 @@ App::SignalState App::getSignalSubscription (int sig) const
int App::setSignalSubscription (int sig, SignalState ss)
{
QSE_ASSERT (sig >= 0 && sig < QSE_NSIGS);
sigset_t sigset;
::sigemptyset (&sigset);
::sigaddset (&sigset, sig);
::sigprocmask (SIG_BLOCK, &sigset, QSE_NULL);
int n;
{
ScopedMutexLocker sml(g_app_mutex);
n = this->set_signal_subscription_no_mutex(sig, ss);
}
::sigprocmask (SIG_UNBLOCK, &sigset, QSE_NULL);
return n;
SigScopedMutexLocker sml(g_app_mutex);
return this->set_signal_subscription_no_mutex(sig, ss);
}
int App::set_signal_subscription_no_mutex (int sig, SignalState reqstate)
@ -342,7 +367,7 @@ int App::set_signal_subscription_no_mutex (int sig, SignalState reqstate)
QSE_ASSERT (sl._prev == QSE_NULL);
if (!sl._next)
{
if (App::unset_signal_handler_no_mutex (sig) <= -1) return -1;
if (App::unset_signal_handler_no_mutex(sig, true) <= -1) return -1;
}
g_app_sig[sig] = sl._next;
}
@ -372,7 +397,7 @@ int App::set_signal_subscription_no_mutex (int sig, SignalState reqstate)
else
{
// no application is set to accept this signal.
// this is the first time to
// it is the first time to set the system-level signal handler.
if (App::set_signal_handler_no_mutex(sig, App::handle_signal) <= -1)
{
// roll back
@ -397,95 +422,6 @@ int App::set_signal_subscription_no_mutex (int sig, SignalState reqstate)
return reqstate;
}
int App::subscribe_to_signal_no_mutex (int sig, SignalState reqstate)
{
return this->set_signal_subscription_no_mutex (sig, reqstate);
#if 0
_SigLink& sl = this->_sig[sig];
if (QSE_LIKELY(sl._state == SIGNAL_UNHANDLED))
{
QSE_ASSERT (sl._prev == QSE_NULL && sl._next == QSE_NULL);
App* xapp = g_app_sig[sig];
App* xapp_xprev = QSE_NULL;
g_app_sig[sig] = this;
sl._state = SIGNAL_ACCEPTED;
sl._next = xapp;
if (xapp)
{
xapp_xprev = xapp->_sig[sig]._prev;
xapp->_sig[sig]._prev = this;
}
else
{
// no application is set to accept this signal.
// this is the first time to
if (App::set_signal_handler_no_mutex(sig, App::handle_signal) <= -1)
{
// roll back
g_app_sig[sig] = xapp;
if (xapp) xapp->_sig[sig]._prev = xapp_xprev;
sl._state = SIGNAL_UNHANDLED;
sl._next = QSE_NULL;
QSE_ASSERT (sl._prev == QSE_NULL);
return -1;
}
}
QSE_ASSERT (sl._prev == QSE_NULL);
}
else
{
// already configured to receive the signal. change the state only
QSE_ASSERT (g_app_sig[sig] != QSE_NULL);
sl._state = reqstate;
}
return 0;
#endif
}
void App::unsubscribe_from_signal_no_mutex (int sig)
{
this->set_signal_subscription_no_mutex (sig, SIGNAL_UNHANDLED);
#if 0
_SigLink& sl = this->_sig[sig];
if (QSE_UNLIKELY(sl._state == SIGNAL_UNHANDLED))
{
QSE_ASSERT (g_app_sig[sig] != this);
QSE_ASSERT (sl._prev == QSE_NULL && sl._next == QSE_NULL);
// nothing to do
}
else
{
QSE_ASSERT (g_app_sig[sig] != QSE_NULL);
if (g_app_sig[sig] == this)
{
QSE_ASSERT (sl._prev == QSE_NULL);
if (!sl._next) App::unset_signal_handler_no_mutex (sig);
g_app_sig[sig] = sl._next;
}
if (sl._next) sl._next->_sig[sig]._prev = sl._prev;
if (sl._prev) sl._prev->_sig[sig]._next = sl._next;
sl._prev = QSE_NULL;
sl._next = QSE_NULL;
sl._state = SIGNAL_UNHANDLED;
}
#endif
}
void App::unsubscribe_from_all_signals_no_mutex()
{
for (int i = 0; i < QSE_NSIGS; i++)
{
this->unsubscribe_from_signal_no_mutex (i);
}
}
int App::guardProcess (const qse_mchar_t* proc_name, const SignalSet& signals)
{
SignalState old_ss[QSE_NSIGS];

View File

@ -147,7 +147,7 @@ int main ()
UINT codepage = GetConsoleOutputCP();
if (codepage == CP_UTF8)
{
/*SetConsoleOUtputCP (CP_UTF8);*/
/*SetConsoleOutputCP (CP_UTF8);*/
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
}
else

View File

@ -274,7 +274,7 @@ int main ()
UINT codepage = GetConsoleOutputCP();
if (codepage == CP_UTF8)
{
/*SetConsoleOUtputCP (CP_UTF8);*/
/*SetConsoleOutputCP (CP_UTF8);*/
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
}
else

View File

@ -129,7 +129,7 @@ int main ()
UINT codepage = GetConsoleOutputCP();
if (codepage == CP_UTF8)
{
/*SetConsoleOUtputCP (CP_UTF8);*/
/*SetConsoleOutputCP (CP_UTF8);*/
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
}
else
@ -150,96 +150,3 @@ int main ()
return 0;
}
#if 0 ////////////////////////
static int test1 (void)
{
QSE::HeapMmgr heap_mmgr (QSE::Mmgr::getDFL(), 30000);
#if defined(QSE_LANG_CPP11)
QSE::TcpServerL<int(QSE::TcpServer::Worker*)> server (
// workload by lambda
([&server](QSE::TcpServer::Worker* worker) {
qse_char_t addrbuf[128];
qse_uint8_t bb[256];
qse_ssize_t n;
worker->address.toStrBuf(addrbuf, QSE_COUNTOF(addrbuf));
g_prt_mutex.lock();
qse_printf (QSE_T("hello word..from %s -> wid %zu\n"), addrbuf, worker->getWid());
g_prt_mutex.unlock();
while (!server.isStopRequested())
{
if ((n = worker->socket.receive(bb, QSE_COUNTOF(bb))) <= 0)
{
g_prt_mutex.lock();
qse_printf (QSE_T("%zd bytes received from %s\n"), n, addrbuf);
g_prt_mutex.unlock();
break;
}
worker->socket.send (bb, n);
}
g_prt_mutex.lock();
qse_printf (QSE_T("byte to %s -> wid %zu\n"), addrbuf, worker->getWid());
g_prt_mutex.unlock();
return 0;
}),
&heap_mmgr
);
#else
QSE::TcpServerF<ClientHandler> server (&heap_mmgr);
#endif
server.setThreadStackSize (256000);
g_server = &server;
//server.start (QSE_T("0.0.0.0:9998"));
server.start (QSE_T("[::]:9998,0.0.0.0:9998"));
//server.start (QSE_T("[fe80::1c4:a90d:a0f0:d52%wlan0]:9998,0.0.0.0:9998"));
g_server = QSE_NULL;
return 0;
}
static void handle_sigint (int sig)
{
if (g_server) g_server->stop ();
}
int main ()
{
#if defined(_WIN32)
char locale[100];
UINT codepage = GetConsoleOutputCP();
if (codepage == CP_UTF8)
{
/*SetConsoleOUtputCP (CP_UTF8);*/
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
}
else
{
qse_mbsxfmt (locale, QSE_COUNTOF(locale), ".%u", (unsigned int)codepage);
setlocale (LC_ALL, locale);
/*qse_setdflcmgrbyid (QSE_CMGR_SLMB);*/
}
#else
setlocale (LC_ALL, "");
/*qse_setdflcmgrbyid (QSE_CMGR_SLMB);*/
#endif
qse_open_stdsios ();
//QSE::App::setSignalHandler (SIGINT, handle_sigint);
test1();
//QSE::App::unsetSignalHandler (SIGINT);
qse_close_stdsios ();
return 0;
}
#endif ////////////////////////

View File

@ -126,7 +126,7 @@ int main ()
UINT codepage = GetConsoleOutputCP();
if (codepage == CP_UTF8)
{
/*SetConsoleOUtputCP (CP_UTF8);*/
/*SetConsoleOutputCP (CP_UTF8);*/
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
}
else

View File

@ -117,7 +117,7 @@ int main ()
UINT codepage = GetConsoleOutputCP();
if (codepage == CP_UTF8)
{
/*SetConsoleOUtputCP (CP_UTF8);*/
/*SetConsoleOutputCP (CP_UTF8);*/
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
}
else

View File

@ -263,7 +263,7 @@ int main ()
UINT codepage = GetConsoleOutputCP();
if (codepage == CP_UTF8)
{
/*SetConsoleOUtputCP (CP_UTF8);*/
/*SetConsoleOutputCP (CP_UTF8);*/
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
}
else

View File

@ -158,7 +158,7 @@ int main ()
UINT codepage = GetConsoleOutputCP();
if (codepage == CP_UTF8)
{
/*SetConsoleOUtputCP (CP_UTF8);*/
/*SetConsoleOutputCP (CP_UTF8);*/
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
}
else