I have a program which needs to be able to handle SIGTERM. For that, I need a sig_atomic_t
global flag that the sigterm handler will set. And for the main code to be able to reliably read that variable, I need to use a membarrier both in the handler and in the main code.
As I have it now, it is like this:
static int mb_cmd;
static sig_atomic_t sigterm;
static
int mb_init(void);
static
int sigterm_init(void);
static
void sigterm_handler(int sig);
inline
int membarrier(int cmd, int flags)
{
return syscall(__NR_membarrier, cmd, flags);
}
int main(void)
{
int status;
status = 1;
if (sigterm_init())
goto err;
do {
// do stuff
asm volatile ("" : : : "memory");
} while (!sigterm);
return 0;
err:
fprintf(stderr, "ERROR: main(): %i\n", status);
perrorx(NULL);
return status;
}
static
int mb_init(void)
{
static bool done = false;
int cmd;
int status;
if (done)
return 0;
status = 1;
cmd = membarrier(MEMBARRIER_CMD_QUERY, 0);
if (cmd < 0)
goto err;
if (cmd & MEMBARRIER_CMD_PRIVATE_EXPEDITED) {
status = 2;
mb_cmd = MEMBARRIER_CMD_PRIVATE_EXPEDITED;
if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0))
goto err;
} else if (cmd & MEMBARRIER_CMD_GLOBAL_EXPEDITED) {
status = 3;
mb_cmd = MEMBARRIER_CMD_GLOBAL_EXPEDITED;
if (membarrier(MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED, 0))
goto err;
} else {
mb_cmd = MEMBARRIER_CMD_GLOBAL;
}
status = 4;
if (membarrier(mb_cmd, 0))
goto err;
done = true;
return 0;
err:
fprintf(stderr, "ERROR: mb_init(): %i\n", status);
return status;
}
static
int sigterm_init(void)
{
struct sigaction sa = {0};
int status;
status = 1;
if (mb_init())
goto err;
sigterm = false;
membarrier(mb_cmd, 0);
status++;
sigemptyset(&sa.sa_mask);
sa.sa_handler = &sigterm_handler;
if (sigaction(SIGTERM, &sa, NULL))
goto err;
return 0;
err:
fprintf(stderr, "ERROR: sigterm_init(): %i\n", status);
return status;
}
static
void sigterm_handler(int sig)
{
(void)sig;
sigterm = true;
membarrier(mb_cmd, 0);
}
When I run the program on my computer it works fine, but on docker it shows the following error (errno
is 1):
ERROR: mb_init(): 1
ERROR: sigterm_init(): 1
ERROR: main(): 1
./rob:
rob.c:184:
main():
E1 - Operation not permitted
How can I use a memory barrier in a program that should run on docker?