установить кодовый поток прыжков и длинных прыжков в c

Я пытаюсь изучить setjump и longjump на C. Может ли кто-нибудь помочь мне с выводом следующего кода вместе с потоком кода и объяснением случаев. Я вызвал функцию funcall() в коде. Аварийный сигнал вызывается для первой итерации, но в последующих итерациях аварийный сигнал не вызывается. Почему это так? Предотвращает ли alarm(0) любые будущие запросы сигналов тревоги?

РЕДАКТИРОВАТЬ: даже после удаления строки «print_T()» в обработчике сигналов код не запускается.

#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <time.h>

#define LEN 50

jmp_buf po;

void print_T() {
    time_t rawtime;
    struct tm * timeinfo;

    time(&rawtime);
    timeinfo = localtime ( &rawtime );
    printf ( "Current local time and date: %s", asctime (timeinfo) );
}



static void ti() {
    print_T();
    longjmp(po,1);
}
int funcall(int reply) {


    static int p;
    p = 0;
    signal(SIGALRM, ti);
    int q = setjmp(po);
    if(q == 0)  
        printf("the value BEFORE setjmp %d for reply %d\n", p, reply);
    else 
        printf("the value AFTER setjmp %d for reply %d\n", p, reply);
    alarm(5);

    if(p > 0) {
        printf("INVOKING THE ALARM");
        alarm(0);
        return -1;
    }

    p++;    
    for(int i = 0; i < 100000; i++) 
        for(int j = 0; j < 100000; j++);
    return 0;

}

int main() {

    int a;
    int reply;
    time_t start, end;
    for(reply=0; ; reply++) {
        printf("~~~~~~~~~~~~~~~~~~~~~~~~~ITERATION NUMBER  %d\n", reply);

        time(&start);
        a = funcall(reply);
        time(&end);
        double tin = difftime(end, start);
        printf("*********************ITERATION END  and a returned is %d after %f\n", a, tin );
        double tidiff = difftime(end, start);
        if(a < 0)
            if(reply == 10) {
                break;
           }

    }

}

person nalin kanoongo    schedule 15.11.2017    source источник
comment
Я предлагаю вам прочитать, например. Сначала longjmp() из обработчика сигнала. То, что вы делаете, может быть плохой идеей.   -  person Some programmer dude    schedule 15.11.2017
comment
@Someprogrammerdude здесь много плохих идей, например, вызов неасинхронно-безопасных функций из обработчика сигналов.   -  person EOF    schedule 15.11.2017
comment
@EOF, пожалуйста, уточните. Я впервые использую setjmp и longjmp   -  person nalin kanoongo    schedule 15.11.2017
comment
Помимо плохих идей, здесь, похоже, это работает на Ubuntu 16.04 Linux.   -  person marcolz    schedule 15.11.2017
comment
@marcolz, не могли бы вы поделиться результатом. Кажется, это не работает для меня   -  person nalin kanoongo    schedule 15.11.2017
comment
@nalinkanooongo Проблема не связана с setjmp(). Исследуйте асинхронную безопасность для функций C.   -  person EOF    schedule 15.11.2017
comment
@nalinkanoongo Конечно. Я добавил включение для unistd.h (для сигнала тревоги()), и он дал мне: pastebin.com/zacDk7mx   -  person marcolz    schedule 15.11.2017
comment
@EOF, какими могут быть возможные результаты вызова longjmp из обработчика сигналов.   -  person nalin kanoongo    schedule 15.11.2017
comment
@marcoz спасибо. Это зависит от платформы? Я не получаю вывод, но вы можете запустить его на Ubuntu 16.04.   -  person nalin kanoongo    schedule 15.11.2017
comment
Я пытаюсь выучить setjump и longjump на C. Почему? Нет причин изучать эти функции — их никогда нельзя использовать ни для каких целей.   -  person Lundin    schedule 15.11.2017
comment
На самом деле я просматривал один из кодов демона freebsd. Они использовали его.. Часть работы   -  person nalin kanoongo    schedule 15.11.2017
comment
int q = setjmp(po); Вы не можете присвоить (или, что еще хуже, использовать его как выражение инициализации) возвращаемое значение из setjump, вы можете только протестировать его.   -  person wildplasser    schedule 15.11.2017
comment
@wildplasser взгляните на эту ссылку. /   -  person nalin kanoongo    schedule 15.11.2017
comment
static void ti() {--› static void ti(int signum) { И sigsetjmp() / siglongjmp()   -  person wildplasser    schedule 15.11.2017


Ответы (1)


Поскольку я не могу комментировать какие-либо сообщения, кроме моего, поскольку моя репутация меньше 50, вот вывод, когда ваш код выполняется на mac os:

Я не вижу никаких проблем с вашим кодом, поскольку alarm(5) вызывается столько раз, сколько вызывается funcall().

Для каждого вызова funcall() первый вызов alarm(5) устанавливает сигнал SIGALRM, который будет доставлен вызывающему процессу (который является ничем иным, как выполняемой функцией/потоком, выполняющим функцию) через 5 секунд, в то время как оставшаяся часть кода выполняется.

Поскольку при каждом вызове статической переменной funcall() p устанавливается значение 0, блок if(p > 0){...} не будет выполняться до тех пор, пока p не станет больше 0, что происходит только в том случае, если следующий оператор, следующий за телом этого блока, p++ увеличивает p и делая его больше нуля, выполняется.

Выполнение вышеупомянутого блока if и, следовательно, вызов alarm(0) зависит от времени, которое требуется циклу for после p++ для завершения. Если выполнение цикла for завершится в течение 5 секунд, оператор return 0 вернет управление вызывающей функции. return отменит все запросы сигналов тревоги и уничтожит стек вызовов функций. Итак, в данном случае alarm(0) не вызывается.

Затем, если выполнение цикла for занимает > 5 секунд (игнорируя все задержки планирования, которые могут произойти и могут время от времени приводить к непредвиденному поведению), будет запущен ожидающий сигнал тревоги, что приведет к вызову обработчика сигнала ti(). Когда вызывается обработчик сигнала ti(), выполняется вызов longjump(), и выполнение снова начинается с вызывающей инструкции setjump(). Когда контроль времени достигает alarm(0) (при условии, что цикл for продолжает выполняться до тех пор, пока предыдущий блок if не выполняется во второй раз), все оставшиеся запросы сигналов тревоги отменяются этим вызовом. Таким образом, alarm(0) отменяет все ожидающие запросы сигналов тревоги после p>0, а цикл for занимает более 5 секунд.

Вот выполнение, записанное через asciinema https://asciinema.org/a/fyZX7CRoikq5kLJS2t0Og2rot< /а>

А вот скриншот сеанса asciinema после завершения выполнения.

скриншот выходных данных сеанса asciinema

person yabhishek    schedule 15.11.2017