1

I'm just using the function alarm to skip the getchar, but something is not going well because it only skips once, and I want it indefinitely.

Example:

#include <signal.h>

int duration = 2;

main() {
     cicleProgram();
}

void cicleProgram(){

  while(opcion != 'q' && opcion != 'Q'){

    signal(SIGALRM, (void*)cicleProgram);
    alarm(duration);

    opcion = getchar();
  }
}

What am I doing wrong?

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
DAM
  • 11
  • 1
  • 1
    Post definition of `opcion`. – chux - Reinstate Monica Aug 24 '16 at 04:23
  • 1
    You have set circleProgram as a signal handler for SIGALRM. When a SIGALRM is raised, the operating system seems to assume that your program is busy processing that SIGALRM until your signal handler returns, so it won't send you another one. – user253751 Aug 24 '16 at 05:07
  • You're also likely deadlocking - you can only use [async-signal-safe](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04) functions in a signal handler. Page down - there's a list of functions that POSIX requires to be async-signal-safe. In your implementation, you're likely to be in `getchar()` waiting for input when the alarm signal is sent which causes another invocation of `circleprogram()` to be started asynchronously - outside the normal program flow. That tries to call `getchar()` but the original call has the input stream locked - a deadlock. – Andrew Henle Aug 24 '16 at 13:39
  • so could i add some control in that "while" in order to evaluate the signal alarm and avoid the deadlock? thanks! – DAM Sep 29 '16 at 03:44

1 Answers1

1

You're using cicleProgram() as your signal handler (despite it having the wrong type — it should take an int argument). That means you never return from the signal handler until you type q or Q, and the system is probably blocking the signal until the first signal handler returns. So, you never get the second signal — it is blocked.

Use a separate signal handler function. See also What is the difference between sigaction() and signal()? and use sigaction() in preference to signal().

And use int main(void) — with at least the return type. Even the old (C99) version of the standard requires that, let alone the current (C11) standard. We've progressed to the 21st Century; don't code in 20th Century C!

See also How to avoid using printf() in a signal handler? for information on what you can do in a signal handler.


Could I add some control in that "while" in order to evaluate the signal alarm and avoid the deadlock?

There are multiple problems with the original code, and not all possible problems were diagnosed. An additional problem was that if the alarm fired, there was nothing to set the alarm again, so the program falls into waiting until you type a character.

Here's some experimental code you play with:

#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

static int duration = 2;
static volatile sig_atomic_t alarm_fired = 0;

static void alarm_handler(int signum)
{
    //signal(SIGALRM, alarm_handler);
    write(STDOUT_FILENO, "Signalled!\n", 11);
    alarm_fired = signum;
    alarm(duration);
}

static void cicleProgram(void)
{
    int opcion = 0;
    while (opcion != 'q' && opcion != 'Q')
    {
        signal(SIGALRM, alarm_handler);
        alarm(duration);
        if ((opcion = getchar()) == EOF)
            clearerr(stdin);
        if (alarm_fired)
        {
            alarm_fired = 0;
            printf("Alarm!\n");
        }
        printf("c = %d\n", opcion);
    }
}

static void actionProgram(void)
{
    struct sigaction sa = { 0 };
    sa.sa_handler = alarm_handler;
    sa.sa_flags = 0;
    sigfillset(&sa.sa_mask);
    sigaction(SIGALRM, &sa, 0);

    int opcion = 0;
    while (opcion != 'q' && opcion != 'Q')
    {
        alarm(duration);
        if ((opcion = getchar()) == EOF)
            clearerr(stdin);
        if (alarm_fired)
        {
            alarm_fired = 0;
            printf("Alarm!\n");
        }
        printf("c = %d\n", opcion);
    }
}

int main(void)
{
    printf("Using signal (q to quit):\n");
    cicleProgram();
    printf("Using sigaction (q to quit):\n");
    actionProgram();
    return 0;
}

There are two active functions, each with a loop. The first is based on your original cicleProgram() but the function has been revamped; it is no longer the signal handler. I am running on Mac OS X (BSD-based), and these systems do not require you to reset the signal() handler in the signal handler function. The second function, actionProgram(), uses sigaction() instead of signal(). It probably isn't necessary, but it gives you something to look at. The absence of SA_RESTART in the sa.sa_flags element means that the read() system call reports that it was interrupted each time the signal goes off. The code in the signal_handler() doesn't use disallowed function calls.

Example output (program name al97):

$ ./al97
Using signal (q to quit):
Signalled!
Signalled!
Signalled!
Signalled!
WonderfulSignalled!

Alarm!
c = 87
c = 111
c = 110
c = 100
c = 101
c = 114
c = 102
c = 117
c = 108
c = 10
Signalled!
Signalled!
q
Alarm!
c = 113
Using sigaction (q to quit):
c = 10
Signalled!
Alarm!
c = -1
Signalled!
Alarm!
c = -1
Signalled!
Alarm!
c = -1
Signalled!
Alarm!
c = -1
ASignalled!
Alarm!
c = -1
lso workingSignalled!
Alarm!
c = -1

c = 65
c = 108
c = 115
c = 111
c = 32
c = 119
c = 111
c = 114
c = 107
c = 105
c = 110
c = 103
c = 10
qSignalled!
Alarm!
c = -1

c = 113
$

There were some quite long pauses in the run, but you can experiment on your machine. You may need to reinclude the signal() in the alarm_handler() function for cicleProgram() and use a different handler (that doesn't use signal(), as now) for actionProgram().

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • so could i add some control in that "while" in order to evaluate the signal alarm and avoid the deadlock? thanks! – DAM Sep 29 '16 at 03:43
  • thanks a lot! After I'll prove that code of you and i'll see what happens more closely really thanks – DAM Sep 29 '16 at 17:35
  • it works very nice! and I got the reference I needed so it was very usefull! thanks a lot – DAM Oct 20 '16 at 18:50