简体   繁体   中英

to terminate the execution of signal handler in c

i am currently working on project involving the interfacing of an ADC with Ras.-Pi using SPI communication. In the project I am controlling the initialisation of SPI using a timer, which then initiates a signal handler. In the signal handler the SPI transmission takes place and value is being stored in a variable, this variabler i am accesing in a thread and storing the recieved value in an array. The code runs but the program never comes out of the signal handler. I want the handler to jump to the thread to store the recieved value everytime it processes a value. Can someone point me to something reliable.

void getSPIvalues(){ // A new Thread which runs parallel and get the values from ADC over SPI
    printf("inside thread function\n");
    timer_useconds(100, 1);
    spiValues[i] = rawData;
    printf("from thread, value = %d\n", spiValues[i]);
    i++;
}

void signalHandler(int sig){ 
    printf("inside handler function\n");
    PWMGenerate(0, 26, 2);  //Zyklus = 960 ns, Freuquency = 1,1 MHz, duty clycle= 8 %
    char data[2];
    bcm2835_spi_transfern(data, sizeof(data));
    rawData = (int)(data[0] << 8 | data[1]);
    bcm2835_gpio_write(PIN, LOW);
}

    //Handler Installation
    memset(&sa, 0, sizeof(sa));
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = &signalHandler;
    sigaction(SIGVTALRM, &sa, NULL);

If I understand correctly, you want a "status update" every x useconds of process execution (rather than of wall clock time, as SIGVTALRM implies ITIMER_VIRTUAL to me).

The safest, simplest way to do this will be to accept a pending signal , instead of delivering that signal to a signal handler.

Before spawning any threads, use pthread_sigmask to SIG_BLOCK at least SIGVTALRM. All new threads will inherit that signal mask. Then, spawn your status thread, detached, which sets an intervalic virtual clock timer and loops, waiting to accept VTALRM:

static void *
my_status_thread(void *ignored) { // spawn me with VTALRM blocked
    sigset_t desired;             // for me and everyone else!

    sigemptyset(&desired);
    sigaddset(&desired, SIGVTALRM);

    set_itimer_virtual(100, 1);  // setitimer()

    while (1) {
        int s;
        (void)sigwait(&desired, &s);
        // we got VTALRM, pull the data
        PWMGenerate(...);
        ....
        printf("value is %d\n", ...);
    }

    return NULL; // not reached
}

Aside

It is possible to do this correctly with signal handlers.

It's quite nuanced, and the nuances matter. You should probably be aware that sigaction is preferred over signal and why. That signal disposition (a registered "handler" or "behavior") is a global process attribute, though signal delivery per se and signal masking are per-thread. That sig_atomic_t doesn't necessarily mean volatile , and why you'd care. That very, very few functions can be safely invoked within a signal handler. That sigemptyset(&sa.sa_mask) is, in my opinion, a bit cargo-culty, and you almost certainly want a full mask inside any consequential handlers.

Even then, it's just not worth it. Signal acceptance is a superior idiom to delivery: you react to signals when and where it is safe for you to do so.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM