added the ignore_if_unhandled parameter to App::neglectsignal().
added App::logfmt() and App::logfmtv() added QSE::TcpServerFD<F,D> and QSE::ThreadFD<F,D>
This commit is contained in:
parent
9a0f2e15b8
commit
f95e9d36cf
@ -32,12 +32,20 @@
|
|||||||
#include <qse/cmn/Mmged.hpp>
|
#include <qse/cmn/Mmged.hpp>
|
||||||
#include <qse/cmn/Bitset.hpp>
|
#include <qse/cmn/Bitset.hpp>
|
||||||
#include <qse/cmn/time.h>
|
#include <qse/cmn/time.h>
|
||||||
|
#include <qse/si/Mutex.hpp>
|
||||||
#include <qse/si/os.h>
|
#include <qse/si/os.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
QSE_BEGIN_NAMESPACE(QSE)
|
QSE_BEGIN_NAMESPACE(QSE)
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
|
||||||
|
#define QSE_APP_LOG_ENABLED(app, mask) (((app)->getLogMask() & mask) == mask)
|
||||||
|
#define QSE_APP_LOG0(app, mask, fmt) do { if (QSE_APP_LOG_ENABLED(app, mask)) app->logfmt(mask, fmt); } while(0)
|
||||||
|
#define QSE_APP_LOG1(app, mask, fmt, a1) do { if (QSE_APP_LOG_ENABLED(app, mask)) app->logfmt(mask, fmt, a1); } while(0)
|
||||||
|
#define QSE_APP_LOG2(app, mask, fmt, a1, a2) do { if (QSE_APP_LOG_ENABLED(app, mask)) app->logfmt(mask, fmt, a1, a2); } while(0)
|
||||||
|
#define QSE_APP_LOG3(app, mask, fmt, a1, a2, a3) do { if (QSE_APP_LOG_ENABLED(app, mask)) app->logfmt(mask, fmt, a1, a2, a3); } while(0)
|
||||||
|
|
||||||
class App: public Uncopyable, public Types, public Mmged
|
class App: public Uncopyable, public Types, public Mmged
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -94,19 +102,25 @@ public:
|
|||||||
return this->setSignalSubscription(sig, SIGNAL_DISCARDED);
|
return this->setSignalSubscription(sig, SIGNAL_DISCARDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
int neglectSignal (int sig)
|
// The neglectSignal() function restored the signal handler
|
||||||
|
// to the previous signal handler remembered. If no signal
|
||||||
|
// handler was set up before this application object has been
|
||||||
|
// initialized, no signal handler is established for the given
|
||||||
|
// signal. the ignore_if_unhandled is true, this function
|
||||||
|
// sets up signal handle to ignore the handler instead.
|
||||||
|
int neglectSignal (int sig, bool ignore_if_unhandled = false)
|
||||||
{
|
{
|
||||||
return this->setSignalSubscription(sig, SIGNAL_NEGLECTED);
|
return this->setSignalSubscription(sig, SIGNAL_NEGLECTED, ignore_if_unhandled);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*SignalHandler) (int sig);
|
typedef void (*SignalHandler) (int sig);
|
||||||
static qse_size_t _sighrs[2][QSE_NSIGS];
|
static qse_size_t _sighrs[2][QSE_NSIGS];
|
||||||
|
|
||||||
// You may set a global signal handler with setSignalHandler().
|
// You may set a global signal handler with setSignalHandler().
|
||||||
// If an application is subscribing to a single with subscribeToSignal(),
|
// If an application is subscribing to a signal with subscribeToSignal(),
|
||||||
// this function is doomed to fail. If a successful call to
|
// this function is doomed to fail. If a successful call to
|
||||||
// setSignalHandler() has been made withoutut unsetSingalHandler() called
|
// setSignalHandler() has been made without unsetSingalHandler() called
|
||||||
// yet, a subsequence call to subscribeToSignal() is doomed to fail too.
|
// yet, a subsequent call to subscribeToSignal() is doomed to fail too.
|
||||||
// These two different interfaces are mutually exclusive.
|
// These two different interfaces are mutually exclusive.
|
||||||
static int setSignalHandler (int sig, SignalHandler sighr);
|
static int setSignalHandler (int sig, SignalHandler sighr);
|
||||||
static int unsetSignalHandler (int sig, bool ignore = false);
|
static int unsetSignalHandler (int sig, bool ignore = false);
|
||||||
@ -118,6 +132,54 @@ public:
|
|||||||
|
|
||||||
int guardProcess (const SignalSet& signals, const qse_mchar_t* proc_name = QSE_NULL);
|
int guardProcess (const SignalSet& signals, const qse_mchar_t* proc_name = QSE_NULL);
|
||||||
|
|
||||||
|
|
||||||
|
// =============================================================
|
||||||
|
// LOGGING SUPPORT
|
||||||
|
// =============================================================
|
||||||
|
|
||||||
|
enum log_mask_t
|
||||||
|
{
|
||||||
|
LOG_DEBUG = (1 << 0),
|
||||||
|
LOG_INFO = (1 << 1),
|
||||||
|
LOG_WARN = (1 << 2),
|
||||||
|
LOG_ERROR = (1 << 3),
|
||||||
|
LOG_FATAL = (1 << 4),
|
||||||
|
|
||||||
|
LOG_TYPE_0 = (1 << 6),
|
||||||
|
LOG_TYPE_1 = (1 << 7),
|
||||||
|
LOG_TYPE_2 = (1 << 8),
|
||||||
|
LOG_TYPE_3 = (1 << 9),
|
||||||
|
LOG_TYPE_4 = (1 << 10),
|
||||||
|
LOG_TYPE_5 = (1 << 11),
|
||||||
|
LOG_TYPE_6 = (1 << 12),
|
||||||
|
LOG_TYPE_7 = (1 << 13),
|
||||||
|
LOG_TYPE_8 = (1 << 14),
|
||||||
|
LOG_TYPE_9 = (1 << 15),
|
||||||
|
|
||||||
|
LOG_ALL_LEVELS = (LOG_DEBUG | LOG_INFO | LOG_WARN | LOG_ERROR | LOG_FATAL),
|
||||||
|
LOG_ALL_TYPES = (LOG_TYPE_0 | LOG_TYPE_1 | LOG_TYPE_2 | LOG_TYPE_3 | LOG_TYPE_4 | LOG_TYPE_5 | LOG_TYPE_6 | LOG_TYPE_7 | LOG_TYPE_8 | LOG_TYPE_9)
|
||||||
|
};
|
||||||
|
|
||||||
|
void setLogMask (int mask) { this->_log.mask = mask; }
|
||||||
|
int getLogMask () const { return this->_log.mask; }
|
||||||
|
|
||||||
|
void logfmt (int mask, const qse_char_t* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start (ap, fmt);
|
||||||
|
logfmtv (mask, fmt, ap);
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void logfmtv (int mask, const qse_char_t* fmt, va_list ap);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void log_write (int mask, const qse_char_t* msg, qse_size_t len)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
// subclasses should override this if needed.
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
App* _prev_app;
|
App* _prev_app;
|
||||||
App* _next_app;
|
App* _next_app;
|
||||||
@ -133,12 +195,26 @@ private:
|
|||||||
_SigLink _sig[QSE_NSIGS];
|
_SigLink _sig[QSE_NSIGS];
|
||||||
long int _guarded_child_pid;
|
long int _guarded_child_pid;
|
||||||
|
|
||||||
|
struct log_t
|
||||||
|
{
|
||||||
|
log_t (App* app): mask(0), last_mask(0), len(0), mtx(app->getMmgr())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int mask, last_mask;
|
||||||
|
qse_size_t len;
|
||||||
|
qse_char_t buf[256];
|
||||||
|
QSE::Mutex mtx;
|
||||||
|
} _log;
|
||||||
|
|
||||||
static int set_signal_handler_no_mutex (int sig, SignalHandler sighr);
|
static int set_signal_handler_no_mutex (int sig, SignalHandler sighr);
|
||||||
static int unset_signal_handler_no_mutex (int sig, int ignore);
|
static int unset_signal_handler_no_mutex (int sig, int ignore);
|
||||||
int set_signal_subscription_no_mutex (int sig, SignalState reqstate, bool ignore_if_unhandled);
|
int set_signal_subscription_no_mutex (int sig, SignalState reqstate, bool ignore_if_unhandled);
|
||||||
|
|
||||||
void on_guard_signal (int sig);
|
void on_guard_signal (int sig);
|
||||||
static void handle_signal (int sig);
|
static void handle_signal (int sig);
|
||||||
|
|
||||||
|
static int put_char_to_log_buf (qse_char_t c, void* ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
@ -38,9 +38,9 @@ class Mutex: public Uncopyable
|
|||||||
public:
|
public:
|
||||||
friend class Condition;
|
friend class Condition;
|
||||||
|
|
||||||
Mutex() QSE_CPP_NOEXCEPT
|
Mutex (Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT
|
||||||
{
|
{
|
||||||
qse_mtx_init (&this->mtx, QSE_NULL);
|
qse_mtx_init (&this->mtx, mmgr);
|
||||||
}
|
}
|
||||||
~Mutex() QSE_CPP_NOEXCEPT
|
~Mutex() QSE_CPP_NOEXCEPT
|
||||||
{
|
{
|
||||||
|
@ -256,7 +256,6 @@ protected:
|
|||||||
friend class TcpServer::Worker;
|
friend class TcpServer::Worker;
|
||||||
virtual int handle_worker (Worker* worker) = 0;
|
virtual int handle_worker (Worker* worker) = 0;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void delete_all_workers (Worker::State state) QSE_CPP_NOEXCEPT;
|
void delete_all_workers (Worker::State state) QSE_CPP_NOEXCEPT;
|
||||||
|
|
||||||
@ -283,7 +282,29 @@ public:
|
|||||||
TcpServerF (F&& f, Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: TcpServer(mmgr), __lfunc(QSE_CPP_RVREF(f)) {}
|
TcpServerF (F&& f, Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: TcpServer(mmgr), __lfunc(QSE_CPP_RVREF(f)) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
F __lfunc;
|
||||||
|
|
||||||
|
int handle_worker (Worker* worker)
|
||||||
|
{
|
||||||
|
return this->__lfunc(this, worker);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// functor + extra data in the functor
|
||||||
|
template <typename F, typename D>
|
||||||
|
class QSE_EXPORT TcpServerFD: public TcpServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TcpServerFD (Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: TcpServer(mmgr) {}
|
||||||
|
TcpServerFD (const F& f, Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: TcpServer(mmgr), __lfunc(f) {}
|
||||||
|
TcpServerFD (const D& d, Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: TcpServer(mmgr), __lfunc(d) {}
|
||||||
|
#if defined(QSE_CPP_ENABLE_CPP11_MOVE)
|
||||||
|
TcpServerFD (F&& f, Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: TcpServer(mmgr), __lfunc(QSE_CPP_RVREF(f)) {}
|
||||||
|
TcpServerFD (D&& d, Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: TcpServer(mmgr), __lfunc(QSE_CPP_RVREF(d)) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
F __lfunc;
|
F __lfunc;
|
||||||
|
|
||||||
int handle_worker (Worker* worker)
|
int handle_worker (Worker* worker)
|
||||||
@ -346,7 +367,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
class Callable
|
class Callable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -150,6 +150,33 @@ protected:
|
|||||||
F __lfunc;
|
F __lfunc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename F, typename D>
|
||||||
|
class QSE_EXPORT ThreadFD: public Thread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ThreadFD (Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: Thread(mmgr) {}
|
||||||
|
ThreadFD (const F& f, Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: Thread(mmgr), __lfunc(f) {}
|
||||||
|
ThreadFD (const D& d, Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: Thread(mmgr), __lfunc(d) {}
|
||||||
|
#if defined(QSE_CPP_ENABLE_CPP11_MOVE)
|
||||||
|
ThreadFD (F&& f, Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: Thread(mmgr), __lfunc(QSE_CPP_RVREF(f)) {}
|
||||||
|
ThreadFD (D&& d, Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT: Thread(mmgr), __lfunc(QSE_CPP_RVREF(d)) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int call_func (qse_thr_t* thr, void* ctx)
|
||||||
|
{
|
||||||
|
ThreadFD<F,D>* t = (ThreadFD<F,D>*)ctx;
|
||||||
|
return t->__lfunc (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
int start (int flags = 0) QSE_CPP_NOEXCEPT
|
||||||
|
{
|
||||||
|
return qse_thr_start (&this->thr, (qse_thr_rtn_t)ThreadFD<F,D>::call_func, this, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
F __lfunc;
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(QSE_LANG_CPP11)
|
#if defined(QSE_LANG_CPP11)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -99,8 +99,10 @@ QSE_EXPORT int qse_wfmtout (
|
|||||||
);
|
);
|
||||||
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR)
|
#if defined(QSE_CHAR_IS_MCHAR)
|
||||||
|
# define qse_fmtout_t qse_mfmtout_t
|
||||||
# define qse_fmtout(fmt,fo,ap) qse_mfmtout(fmt,fo,ap)
|
# define qse_fmtout(fmt,fo,ap) qse_mfmtout(fmt,fo,ap)
|
||||||
#else
|
#else
|
||||||
|
# define qse_fmtout_t qse_wfmtout_t
|
||||||
# define qse_fmtout(fmt,fo,ap) qse_wfmtout(fmt,fo,ap)
|
# define qse_fmtout(fmt,fo,ap) qse_wfmtout(fmt,fo,ap)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <qse/si/os.h>
|
#include <qse/si/os.h>
|
||||||
#include "../cmn/syscall.h"
|
#include "../cmn/syscall.h"
|
||||||
#include "../cmn/mem-prv.h"
|
#include "../cmn/mem-prv.h"
|
||||||
|
#include "../cmn/fmt-prv.h"
|
||||||
#include <qse/cmn/mbwc.h>
|
#include <qse/cmn/mbwc.h>
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
@ -72,7 +73,7 @@ protected:
|
|||||||
sigset_t oldsigset;
|
sigset_t oldsigset;
|
||||||
};
|
};
|
||||||
|
|
||||||
App::App (Mmgr* mmgr) QSE_CPP_NOEXCEPT: Mmged(mmgr), _prev_app(QSE_NULL), _next_app(QSE_NULL), _guarded_child_pid(-1)
|
App::App (Mmgr* mmgr) QSE_CPP_NOEXCEPT: Mmged(mmgr), _prev_app(QSE_NULL), _next_app(QSE_NULL), _guarded_child_pid(-1), _log(this)
|
||||||
{
|
{
|
||||||
SigScopedMutexLocker sml(g_app_mutex);
|
SigScopedMutexLocker sml(g_app_mutex);
|
||||||
if (!g_app_top)
|
if (!g_app_top)
|
||||||
@ -467,6 +468,8 @@ int App::guardProcess (const SignalSet& signals, const qse_mchar_t* proc_name)
|
|||||||
// child process
|
// child process
|
||||||
this->_guarded_child_pid = -1;
|
this->_guarded_child_pid = -1;
|
||||||
|
|
||||||
|
// the child process has inherited the signal handlers.
|
||||||
|
// restore the signal handlers of the child process to the original handlers.
|
||||||
for (int i = 0; i < QSE_NSIGS; i++)
|
for (int i = 0; i < QSE_NSIGS; i++)
|
||||||
{
|
{
|
||||||
if (signals.isSet(i)) this->setSignalSubscription (i, old_ss[i]);
|
if (signals.isSet(i)) this->setSignalSubscription (i, old_ss[i]);
|
||||||
@ -519,6 +522,59 @@ int App::guardProcess (const SignalSet& signals, const qse_mchar_t* proc_name)
|
|||||||
return seq; // the caller must execute the actual work.
|
return seq; // the caller must execute the actual work.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int App::put_char_to_log_buf (qse_char_t c, void* ctx)
|
||||||
|
{
|
||||||
|
App* app = (App*)ctx;
|
||||||
|
if (app->_log.len >= QSE_COUNTOF(app->_log.buf) - 1) // -1 for the lien terminator appending in App::logfmtv()
|
||||||
|
{
|
||||||
|
app->log_write (app->_log.last_mask, app->_log.buf, app->_log.len);
|
||||||
|
app->_log.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
app->_log.buf[app->_log.len++] = c;
|
||||||
|
if (c == QSE_T('\n'))
|
||||||
|
{
|
||||||
|
app->log_write (app->_log.last_mask, app->_log.buf, app->_log.len);
|
||||||
|
app->_log.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::logfmtv (int mask, const qse_char_t* fmt, va_list ap)
|
||||||
|
{
|
||||||
|
/*if (this->threaded)*/ this->_log.mtx.lock ();
|
||||||
|
|
||||||
|
if (this->_log.len > 0 && this->_log.last_mask != mask)
|
||||||
|
{
|
||||||
|
if (this->_log.buf[this->_log.len - 1] != QSE_T('\n'))
|
||||||
|
{
|
||||||
|
// no line ending - append a line terminator
|
||||||
|
this->_log.buf[this->_log.len++] = QSE_T('\n');
|
||||||
|
}
|
||||||
|
this->log_write (this->_log.last_mask, this->_log.buf, this->_log.len);
|
||||||
|
this->_log.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_fmtout_t fo;
|
||||||
|
|
||||||
|
fo.count = 0;
|
||||||
|
fo.limit = QSE_TYPE_MAX(qse_size_t) - 1;
|
||||||
|
fo.ctx = this;
|
||||||
|
fo.put = put_char_to_log_buf;
|
||||||
|
#if defined(QSE_CHAR_IS_WCHAR)
|
||||||
|
fo.conv = QSE_NULL;
|
||||||
|
#else
|
||||||
|
fo.conv = QSE_NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
this->_log.last_mask = mask;
|
||||||
|
qse_fmtout(fmt, &fo, ap);
|
||||||
|
|
||||||
|
/*if (this->threaded)*/ this->_log.mtx.unlock ();
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
QSE_END_NAMESPACE(QSE)
|
QSE_END_NAMESPACE(QSE)
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
@ -401,9 +401,13 @@ int TcpServer::start (const qse_char_t* addrs) QSE_CPP_NOEXCEPT
|
|||||||
n = qse_mux_poll(this->listener_list.mux, QSE_NULL);
|
n = qse_mux_poll(this->listener_list.mux, QSE_NULL);
|
||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
this->setErrorCode (E_ESYSERR); // TODO: proper error code conversion
|
qse_mux_errnum_t merr = qse_mux_geterrnum(this->listener_list.mux);
|
||||||
xret = -1;
|
if (merr != QSE_MUX_EINTR)
|
||||||
break;
|
{
|
||||||
|
this->setErrorCode (E_ESYSERR); // TODO: proper error code conversion
|
||||||
|
xret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,12 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FunctorWithI: public Functor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FunctorWithI (int* x) {}
|
||||||
|
};
|
||||||
|
|
||||||
static int func_ptr (QSE::Thread* thr)
|
static int func_ptr (QSE::Thread* thr)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -185,6 +191,12 @@ static int test1 (void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int t = 20;
|
||||||
|
QSE::ThreadFD<FunctorWithI, int*> thr7 (&t);
|
||||||
|
// just keep this here to see if QSE::ThreadFD<> can be instantiated syntatically
|
||||||
|
}
|
||||||
|
|
||||||
while (!g_stopreq)
|
while (!g_stopreq)
|
||||||
{
|
{
|
||||||
if (thr1.getState() == QSE::Thread::TERMINATED &&
|
if (thr1.getState() == QSE::Thread::TERMINATED &&
|
||||||
|
Loading…
Reference in New Issue
Block a user