Как установить ограничение по времени на функцию с безопасной областью

StackOverflow https://stackoverflow.com/questions/3622015

  •  26-09-2019
  •  | 
  •  

Вопрос

Я пытаюсь разработать программу во времени ограничить выполнение функции. В следующем коде у меня есть функция с именем Inc который делает много итераций (имитируется бесконечной петлей). Первая часть каждой итерации довольно длинно, а затем вторая часть, которая должна быть довольно быстро.

Я не против выгрузить исполнение, в то время как в первой части кода, но я хотел бы избежать ухода с тревоги, при выполнении операции записи во второй части.

Моя первая идея состояла в том, чтобы отключить тревогу, прежде чем войти в «безопасный регион», сохраняя оставшееся время. Затем после выхода я бы установил будильник с сохраненным временем. Я не знаю, как это реализовать. Может кто-нибудь помочь мне? Альтернативные методы также приветствуются.

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

pthread_t thread;
FILE *fout;

void *Inc(void *param){

    int i;
    long long int x = 0;

    fout = fopen("file.txt", "w");

    /* Large number of iterations */
    while(1){

        int k = 0;
        for(i=0; i<5000000; i++)
            k += (rand())%3;
        x += k;

        printf("%lld\n", x);
        /* Enter Safe Region */
        fprintf(fout, "%lld\n", x);
        /* Exit Safe Region */
    }   
}

void Finish(int param){
    pthread_cancel(thread);
    fclose(fout);
}

main (){

    pthread_attr_t attr;
    void *status;

    signal(SIGALRM, Finish);
    alarm(10);

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    pthread_create(&thread, &attr, Inc, NULL);
    pthread_attr_destroy(&attr);
    pthread_join(thread, &status);

    printf("Program Finished\n");
}
Это было полезно?

Решение

Очевидная вещь - взять замок перед вызовом pthread_cancel, и держать один и тот же замок через вашу «безопасную область».

К сожалению, вы не можете дождаться mutex или семафора в обработчике сигнала. Но сигналы тревоги не единственный способ сделать что-то через 10 секунд - вместо этого вы могли бы иметь ваш главный нить спать в течение 10 секунд, а затем просыпаться, возьмите замок, отмените рабочей нити, а затем присоединяйтесь к нему.

Конечно, это будет означать, что основной нить будет спать 10 секунд, даже если рабочая нить заканчивается через 5 секунд. Таким образом, вместо сна, у главного потока есть 10-секундный пример ждать на семафоре, который рабочие поток поток, когда он закончится.

Как сон, пример ожидания может завершить ранние из-за сигнала, поэтому обязательно повторите попытку приурошкового ждать в EINTR. Ваши значительные случаи - это EINTR (снова ждать), успех (присоединиться к рабочей нити - не нужно отменять, поскольку он опубликовал семафор), Etimedout (возьмите замок, отменить, соединить), и если вам нравится, другие ошибки. Других ошибок, указанных для sem_timedwait Это должно повлиять на вас, хотя.

Другая идея состоит в том, чтобы заблокировать Sigalrm через вашу «безопасную область», что было бы проще, за исключением того, что (а) я никогда не помню, как безопасно делать ввод / вывод с отключенными сигналами, а (b) ваша рабочая нить может быть запущена »одновременно «С помощью обработчика сигнала (либо действительно одновременно или, по-видимому, так из-за предварительной эмблеции), что означает, что сигнал может быть предпринят, то ваш работник отключает сигналы и входит в критическую область, затем обработчик сигналов отменяет его. Если никто не отвечает, кто на самом деле может вспомнить детали, вот некоторые Информация о блокирующих сигналах.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top