Commit 63c42152 authored by Sid Stenersen's avatar Sid Stenersen
Browse files

fix: improve signal handling and error reporting

parent 2079ee0e
Pipeline #89268 failed with stages
in 75 minutes and 39 seconds
// ============================================================================
// Copyright 2017-2021, Schlumberger
// Copyright 2017-2022, Schlumberger
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
......@@ -18,88 +18,64 @@
#ifndef _WIN32
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include "logger.h"
#include <cerrno>
#include <csignal>
#include <cstring>
namespace
{
/**
* @details a simple scope guard that masks and unmasks a single signal
* @todo arbitrary list of signals instead ?
* Windows ?
*/
template <int tSIGNUM>
class SignalBlockingScopeGuard
{
public:
// ctor from initialization list of ints or int ?
SignalBlockingScopeGuard()
{
int status = 0;
status = sigemptyset(&_sigBlocked);
if (status == -1)
{
perror("SeismicStore : sigemptyset() failed");
}
status = sigaddset(&_sigBlocked, tSIGNUM);
if (status == -1)
{
// FIXME : only EINVAL
perror("SeismicStore : sigaddset() failed");
}
status = pthread_sigmask(SIG_BLOCK, &_sigBlocked, &_sigSaved);
if (status == -1)
{
perror("SeismicStore : pthread_sigmask( SIG_BLOCK, ... ) failed : YOUR SIGNAL IS NOT MASKED IN CURRENT THREAD");
}
test(true, sigemptyset(&_sigBlocked), "sigemptyset()");
test(true, sigaddset(&_sigBlocked, tSIGNUM), "sigaddset()");
test(true, pthread_sigmask(SIG_BLOCK, &_sigBlocked, &_sigSaved), "pthread_sigmask( SIG_BLOCK, ... )",
" : YOUR SIGNAL IS NOT MASKED IN CURRENT THREAD");
}
~SignalBlockingScopeGuard()
{
// is SIGPIPE already pending
sigset_t sigPending;
int status = 0;
int found = 1;
status = sigpending(&sigPending);
if (status == 0)
if (test(true, sigpending(&sigPending), "sigpending()") ||
sigismember(&sigPending, tSIGNUM) == 1)
{
found = sigismember(&sigPending, tSIGNUM);
}
else
{
perror("SeismicStore : sigispending() failed");
}
if (found)
{
// logging ?
// accept the signal already pending.
struct timespec zeroTime;
memset(&zeroTime, 0, sizeof(struct timespec));
status = sigtimedwait(&_sigBlocked, 0, &zeroTime);
if (status == -1)
timespec zeroTime = { 0, 0 };
if (test(false, sigtimedwait(&_sigBlocked, 0, &zeroTime), "sigtimedwait()", " to discard signal") != -1)
{
perror("SeismicStore : sigtimedwait() failed to discard signal");
_log(1) << "SeismicStore : correctly discarded already pending signal";
}
}
// restore the signal mask to its original state
status = pthread_sigmask(SIG_SETMASK, &_sigSaved, 0);
test(true, pthread_sigmask(SIG_SETMASK, &_sigSaved, 0), "pthread_sigmask( SIG_SETMASK, ... )",
" : YOUR SIGNAL IS STILL MASKED IN CURRENT THREAD");
}
if (status == -1)
private:
sigset_t _sigSaved, _sigBlocked;
seismicdrive::Logger _log;
int test(bool expectZero, int status, const std::string &action, const std::string &tail = "")
{
if (expectZero ? status : status == -1)
{
perror("SeismicStore : pthread_sigmask( SIG_SETMASK, ... ) failed : YOUR SIGNAL IS STILL MASKED IN CURRENT THREAD");
char e[999];
strerror_r(errno, e, sizeof e);
auto s = "SeismicStore : " + action + " failed" + tail + " : " + e;
_log(0) << s;
}
return status;
}
private:
sigset_t _sigSaved;
sigset_t _sigBlocked;
};
typedef SignalBlockingScopeGuard<SIGPIPE> SigPipeMask;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment