Question

ualarm() is not implemented in Android version of libc, bionic (check Bionic unistd.h). Moreover, ualarm() is obsolete.

I am porting an application on Android NDK so I need an equivalent of ualarm(999999,999999), i.e. something that would send a SIGALRM periodically (every second).

Maybe with timer_create() ? It seems to be implemented in Bionic. But the example in the man page is really not trivial...

Code i'm willign to port to Android (NDK):

/* 
 * Set a recurring 1 second timer that will call sigalrm() and switch to 
 * a new channel.
 */

    act.sa_handler = sigalrm_handler;
    sigaction (SIGALRM, &act, 0);
    ualarm(CHANNEL_INTERVAL, CHANNEL_INTERVAL);
    change_channel(1);

/* Whenever a SIGALRM is thrown, go to the next 802.11 channel */
void sigalrm_handler(int x)
{
    next_channel();
}
Was it helpful?

Solution

OK, create_timer was the key. Too bad nobody answered with an example in time.

I've built this code by simplifying this answer.

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>

// Handler that will be called every its.it_value.tv_sec seconds + its.it_value.tv_nsec nanoseconds until you kill the timer
static void handler(int sig, siginfo_t *si, void *uc)
{
        printf("Caught signal %d from timer\n", sig);
}

int main(int argc, char *argv[])
{
    struct sigevent sev;
    struct itimerspec its;
    sigset_t mask;
    struct sigaction sa;
    timer_t timerid;

    // Define sigaction: handler
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGUSR1, &sa, NULL);

    // Define sigevent
    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIGUSR1;

    // Create the timer
    timer_create(CLOCK_REALTIME, &sev, &timerid);
    its.it_value.tv_sec = 1;
    its.it_value.tv_nsec = 0;
    its.it_interval.tv_sec = its.it_value.tv_sec;
    its.it_interval.tv_nsec = its.it_value.tv_nsec;
    timer_settime(timerid, 0, &its, NULL);

    // Sleeps (100sec) is aborted: its default behavior is to wake up when a signal is received (1sec)
    // So we sleep again to properly see the next signal in this example.
    // That's just for the example so that the process doesn't terminate.
    sleep(100); sleep(100); sleep(100); sleep(100); sleep(100); sleep(100);
    exit(EXIT_SUCCESS);
}

Disabling a periodic timer was done with ualarm(0, 0). There was no need to pass a timer in argument. But with time_delete, we need this timer reference. So code must be adapted to remember the timer reference to disable it.

So to pass the timer by reference if needed:

some_function(..., &timerid);
void some_function(..., timer_t *timerid)

And to disable the timer:

timer_delete(timerid);

Also note that ualarm uses SIGALRM signal. In this code we're using SIGUSR1 instead.

SIGALRM, SIGVTALRM and SIGPROF The SIGALRM, SIGVTALRM and SIGPROF signal is sent to a process when the time limit specified in a call to a preceding alarm setting function (such as setitimer) elapses. SIGALRM is sent when real or clock time elapses. SIGVTALRM is sent when CPU time used by the process elapses. SIGPROF is sent when CPU time used by the process and by the system on behalf of the process elapses.

SIGUSR1 and SIGUSR2 The SIGUSR1 and SIGUSR2 signals are sent to a process to indicate user-defined conditions.

There might be timer conflicts if you're using several timers that all uses SIGUSR1. Check the original answer to handle several timers all using SIGUSR1.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top