1

timer_settime() builds timer every second. The signal handler is traffic_measurement_handler. Does traffic_measurement_handler run in a new thread? How to let callback stop when the handler is running?

#define CLOCKID CLOCK_REALTIME
#define SIG SIGUSR1
timer_t timerid;

int main(void)
{
    ..

    build_timer();
    pcap_loop(pcap_handle, -1, callback, NULL);
}

void callback() // callback of Libpcap API: pcap_loop()
{
    detect_network_traffic(); // stop when timer expires, and then continue                 
                              // to run when traffic_measurement_handler has finished.
}

// timer handler runs every second to update database
void traffic_measurement_handler() 
{
    .. // This block will fetch global variables, so I want to
       // let callback stop when this handler is running.


    // rebuild the timer
    build_timer();

}

// set timer
void build_timer()
{
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = traffic_measurement_handler;
    sigemptyset(&sa.sa_mask);
    sigaction(SIG, &sa, NULL);

    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIG;
    sev.sigev_value.sival_ptr = &timerid;
    timer_create(CLOCKID, &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);
}

Is signal handler safe in a process where only one thread exists?

Added: second version
Is this right?

pthread_t thread_global;

int main(void)
{
    // register SIGUSR1 handler
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = traffic_measurement_handler;
    sigemptyset(&sa.sa_mask);
    sigaction(SIG, &sa, NULL);

    pthread_create(&thread1, NULL, processing_thread, (void *) thread_id1);
    pthread_create(&thread2, NULL, timer_thread, (void *) thread_id2);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);    
}

void *processing_thread(void *thread_id)
{
    pcap_loop(pcap_handle, -1, callback, NULL);
}

void callback() // callback of Libpcap API: pcap_loop()
{
    thread_global = pthread_self();
    detect_network_traffic(); // stop when SIGUSR1 is caught, and then continue                 
                              // to run when traffic_measurement_handler has finished.
}

//update database every second when SIGUSR1 is caught
void traffic_measurement_handler()
{
    ..
}

//This thread is used to notify updating database every second.
void *timer_thread(void *thread_id)
{
    for (; ;) {
        sleep(1);
        pthread_kill(thread_global, SIGUSR1);
    }
}
hel
  • 581
  • 10
  • 26
  • 1
    It depends what parameter values you passed to `timer_create`. Read the [timer_create man page](http://man7.org/linux/man-pages/man2/timer_create.2.html). It tells you how the function is invoked depending on the parameters. Show a [mcve] if you want further help. – kaylum Mar 14 '17 at 05:10
  • @kaylum I've added sample code. – hel Mar 14 '17 at 05:27
  • If you set sigev_notify to SIGEV_THREAD instead of SIGEV_SIGNAL, then the callback will run as a new thread. Now it is running as a signal handler. – avatli Mar 14 '17 at 05:40
  • @Ali Volkan ATLI, thanks. So are `callback` and `traffic_measurement_handler` in the same thread? – hel Mar 14 '17 at 05:52
  • @hel, No, callback is coming from pcap thread but traffic_measurement_handler will be kernel thread if you set sev.sigev_notify to SIGEV_THREAD. Run the code and check it via "top -H -p yourPID" – avatli Mar 14 '17 at 06:00
  • @AliVolkanATLI here `callback` is not timer handler...[pcap_loop](https://linux.die.net/man/3/pcap_loop) – jjm Mar 14 '17 at 06:01
  • I set it as SIGEV_SIGNAL. – hel Mar 14 '17 at 06:02
  • 1
    @hel, still no, 2.6 posix threads, the signal is sent to process, which is received by and handled by root thread. pcap_loop creates another thread, so it will be on different threads – avatli Mar 14 '17 at 06:04
  • @Ali Volkan ATLI. Why is the signal sent to root thread? I thought signal is sent to an unclear thread, root thread or the `callback`. – hel Mar 14 '17 at 06:18

2 Answers2

1

To run the timer handler as thread mode, you have to modify value of sev.sigev_notify; Read the below quote from the man page of timer_create

The sevp.sigev_notify field can have the following values:

   SIGEV_NONE
          Don't asynchronously notify when the timer expires.  Progress
          of the timer can be monitored using timer_gettime(2).

   SIGEV_SIGNAL
          Upon timer expiration, generate the signal sigev_signo for the
          process.  See sigevent(7) for general details.  The si_code
          field of the siginfo_t structure will be set to SI_TIMER.  At
          any point in time, at most one signal is queued to the process
          for a given timer; see timer_getoverrun(2) for more details.

   SIGEV_THREAD
          Upon timer expiration, invoke sigev_notify_function as if it
          were the start function of a new thread.  See sigevent(7) for
          details.

   SIGEV_THREAD_ID (Linux-specific)
          As for SIGEV_SIGNAL, but the signal is targeted at the thread
          whose ID is given in sigev_notify_thread_id, which must be a
          thread in the same process as the caller.  The
          sigev_notify_thread_id field specifies a kernel thread ID,
          that is, the value returned by clone(2) or gettid(2).  This
          flag is intended only for use by threading libraries.

   Specifying sevp as NULL is equivalent to specifying a pointer to a
   sigevent structure in which sigev_notify is SIGEV_SIGNAL, sigev_signo
   is SIGALRM, and sigev_value.sival_int is the timer ID.

Also check man page of timer_settimeman

Here callback will act as different thread , because pcap_loop creates a new thread.

jjm
  • 431
  • 3
  • 19
1
  1. Does traffic_measurement_handler run in a new thread?

In POSIX threads no new thread is created as a result of a signal when sigev_notify = SIGEV_SIGNAL. So in your code you do not create a new thread.

  1. How to let callback stop when the handler is running?

You can set the signal to be handled by the same thread that runs the callback.

POSIX.1 distinguishes the notions of signals that are directed to the process as a whole and signals that are directed to individual threads.

Read Unix pthreads and signals: per thread signal handlers

Community
  • 1
  • 1
Arash
  • 1,950
  • 14
  • 17
  • Yeah. `sigev_notify = SIGEV_SIGNAL`. If this doesn't create new thread, there is only one thread in the whole process. – hel Mar 14 '17 at 06:03
  • How about that library? You give it a callback and it will run that callback when something happens (I don't know that lib). Then there is an event handler running in a different thread in that library. – Arash Mar 14 '17 at 06:16