29    #include <sys/socket.h> 
   43void service_runner::service_thread() {
 
   45        const std::lock_guard<std::mutex> lock(mtx_lifecycle); 
 
   47            service_init_locked(*
this);
 
   49            DBG_PRINT(
"%s::worker Started", name_.c_str());
 
   50        } 
catch(
const std::exception &e) {
 
   53            ERR_PRINT2(
"%s::worker Exception @ service_init_locked: %s", name_.c_str(), e.what());
 
   62    thread_local jau::call_on_release thread_cleanup([&]() { 
 
   63        DBG_PRINT(
"%s::worker::ThreadCleanup: serviceRunning %d -> 0", name_.c_str(), running.load());
 
   68    while( !shall_stop_ ) {
 
   71        } 
catch(
const std::exception &e) {
 
   73            ERR_PRINT2(
"%s::worker Exception @ service_work: %s", name_.c_str(), e.what());
 
   77        const std::lock_guard<std::mutex> lock(mtx_lifecycle); 
 
   80            service_end_locked(*
this);
 
   81        } 
catch(
const std::exception &e) {
 
   82            ERR_PRINT2(
"%s::worker Exception @ service_end_locked: %s", name_.c_str(), e.what());
 
   86        thread_cleanup.set_released();
 
   95    WORDY_PRINT(
"service_runner.sigaction: sig %d, info[code %d, errno %d, signo %d, pid %d, uid %d], pid-self %d (match %d)",
 
   96            sig, info->si_code, info->si_errno, info->si_signo,
 
   97            info->si_pid, info->si_uid,
 
  101    if( !pidMatch || SIGALRM != 
sig ) {
 
 
  111bool service_runner::install_sighandler() noexcept {
 
  112    struct sigaction sa_setup;
 
  115    ::sigemptyset(&(sa_setup.sa_mask));
 
  116    sa_setup.sa_flags = SA_SIGINFO;
 
  117    if( 0 != ::sigaction( SIGALRM, &sa_setup, 
nullptr ) ) {
 
  118        ERR_PRINT(
"service_runner::install_sighandler: Setting sighandler");
 
  121    DBG_PRINT(
"service_runner::install_sighandler: OK");
 
  126    struct sigaction sa_setup;
 
  128    sa_setup.sa_handler = SIG_DFL;
 
  129    ::sigemptyset(&(sa_setup.sa_mask));
 
  130    sa_setup.sa_flags = 0;
 
  131    if( 0 != ::sigaction( SIGALRM, &sa_setup, 
nullptr ) ) {
 
  132        ERR_PRINT(
"service_runner::remove_sighandler: Resetting sighandler");
 
  135    DBG_PRINT(
"service_runner::remove_sighandler: OK");
 
 
  143                               Callback service_end_locked_) noexcept
 
  144: name_( std::move(name__) ),
 
  146  service_work( std::move(service_work_) ),
 
  147  service_init_locked( std::move(service_init_locked_) ),
 
  148  service_end_locked( std::move(service_end_locked_) ),
 
  149  shall_stop_(
true), running(
false),
 
 
  156    DBG_PRINT(
"%s::dtor: Begin", name_.c_str());
 
  158    DBG_PRINT(
"%s::dtor: End", name_.c_str());
 
 
  163        const std::lock_guard<std::mutex> lock_stop(mtx_shall_stop_); 
 
  166    cv_shall_stop_.notify_all(); 
 
 
  174    std::unique_lock<std::mutex> lock(mtx_lifecycle); 
 
  176        const std::lock_guard<std::mutex> lock_stop(mtx_shall_stop_); 
 
  179    cv_shall_stop_.notify_all(); 
 
  186    std::thread t(&service_runner::service_thread, 
this); 
 
  187    thread_id_ = t.native_handle();
 
  192    while( 
false == running && 
false == shall_stop_ ) {
 
 
  201    std::unique_lock<std::mutex> lock(mtx_lifecycle); 
 
  202    const ::pthread_t tid_service = thread_id_;
 
  203    const bool is_service = tid_service == ::pthread_self();
 
  204    DBG_PRINT(
"%s::stop: service[running %d, shall_stop %d, is_service %d, tid %p)",
 
  205              name_.c_str(), running.load(), shall_stop_.load(), is_service, (
void*)tid_service); 
 
  210            if( 0 != tid_service ) {
 
  211                #if JAU_OS_HAS_PTHREAD 
  214                    if( 0 != ( kerr = ::pthread_kill(tid_service, SIGALRM) ) ) {
 
  215                        ERR_PRINT(
"%s::stop: pthread_kill %p FAILED: %d", name_.c_str(), (
void*)tid_service, kerr); 
 
  220                    INFO_PRINT(
"%s::stop: pthread_kill n/a, service %p running", name_.c_str(), (
void*)tid_service); 
 
  226            while( 
true == running && result ) {
 
  227                std::cv_status s { std::cv_status::no_timeout };
 
  233                if( std::cv_status::timeout == s && 
true == running ) {
 
  234                    ERR_PRINT(
"%s::stop: Timeout (force !running): %s", name_.c_str(), 
toString().c_str());
 
  245    DBG_PRINT(
"%s::stop: End: Result %d, %s", name_.c_str(), result, 
toString().c_str());
 
 
  251    std::unique_lock<std::mutex> lock(mtx_lifecycle); 
 
  253    const bool is_service = thread_id_ == ::pthread_self();
 
  254    DBG_PRINT(
"%s::join: is_service %d, %s", name_.c_str(), is_service, 
toString().c_str());
 
  261            while( 
true == running && result ) {
 
  262                std::cv_status s { std::cv_status::no_timeout };
 
  268                if( std::cv_status::timeout == s && 
true == running ) {
 
  269                    ERR_PRINT(
"%s::join: Timeout (force !running): %s", name_.c_str(), 
toString().c_str());
 
  280    DBG_PRINT(
"%s::join: End: Result %d, %s", name_.c_str(), result, 
toString().c_str());
 
 
  285    return "ServiceRunner["+name_+
", running "+std::to_string(
is_running())+
", shall_stop "+std::to_string(shall_stop_)+
 
 
bool stop() noexcept
Stops this service, if running.
 
function< void(service_runner_ref)> Callback
 
static bool remove_sighandler() noexcept
Remove the sighandler.
 
fraction_i64 service_shutdown_timeout() const noexcept
Returns maximum duration in fractions of seconds to wait for service to stop at stop() and join(),...
 
void set_shall_stop() noexcept
Marks the service thread to stop in due process by flagging shall stop to true.
 
service_runner(std::string name, fraction_i64 service_shutdown_timeout, Callback service_work, Callback service_init_locked=Callback(), Callback service_end_locked=Callback()) noexcept
Service runner constructor.
 
bool is_running() const noexcept
Returns true if service is running.
 
static const ::pid_t pid_self
 
bool join() noexcept
Blocks the current thread until service is stopped or returns immediately if not running or called fr...
 
std::string toString() const noexcept
Returns a string representation of this service.
 
~service_runner() noexcept
Service runner destructor.
 
void start() noexcept
Starts this service, if not running already.
 
#define ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
 
#define WORDY_PRINT(...)
Use for environment-variable environment::VERBOSE conditional verbose messages, prefix '[elapsed_time...
 
#define DBG_PRINT(...)
Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] De...
 
#define ERR_PRINT2(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
 
fraction_timespec getMonotonicTime() noexcept
Returns current monotonic time since Unix Epoch 00:00:00 UTC on 1970-01-01.
 
fraction< int64_t > fraction_i64
fraction using int64_t as integral type
 
constexpr bool has_pthread() noexcept
Evaluates true if platform supports posix compatible threading.
 
void zero_bytes_sec(void *s, size_t n) noexcept __attrdecl_no_optimize__
Wrapper to ::explicit_bzero(), ::bzero() or ::memset(), whichever is available in that order.
 
std::string toHexString(const void *data, const nsize_t length, const lb_endian_t byteOrder=lb_endian_t::big, const LoUpCase capitalization=LoUpCase::lower, const PrefixOpt prefix=PrefixOpt::prefix) noexcept
Produce a hexadecimal string representation of the given lsb-first byte values.
 
constexpr const jau::fraction_i64 zero(0l, 1lu)
zero is 0/1
 
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
 
void INFO_PRINT(const char *format,...) noexcept
Use for unconditional informal messages, prefix '[elapsed_time] Info: '.
 
std::cv_status wait_until(std::condition_variable &cv, std::unique_lock< std::mutex > &lock, const fraction_timespec &absolute_time, const bool monotonic=true) noexcept
wait_until causes the current thread to block until the condition variable is notified,...
 
static void sigaction_handler(int sig, siginfo_t *info, void *ucontext) noexcept
 
Timespec structure using int64_t for its components in analogy to struct timespec_t on 64-bit platfor...