Как освободить динамически размещаемую переменную по SIGTERM? - PullRequest
0 голосов
/ 02 мая 2009

Я работаю над кодом примерно так

... HEADERS ...

int *var;

void child() {
  ... //some work
  free(var);
  exit(EXIT_SUCCESSFUL);
}

int main(void) {
  ...
  //allocate variable
  var = (int *) malloc(N*sizeof(int));
  ... //work with var

  for(int i; i<PROC_COUNT; i++) {
    pid_t child = fork();
    if(pid == 0) {
      child(); //main function of new proces
      break;
    }
    elseif(pid < 0) {
      //there is enormous problem -> kill every proces
      kill(0, SIGTERM);
      waitpid(0, NULL, 0); //wait for children
      free(var);
      exit(EXIT_FAILURE);
    }

  }
  free(var);
  return EXIT_SUCCESS;
}

Когда процесс разветвляется, все переменные тоже клонируются. В обычном случае все копии var освобождаются.

Если есть ошибка по fork(), я посылаю сигнал SIGTERM всем созданным процессам. И мне нужно написать обработчик сигнала для SIGTERM, который освобождает var и завершает приложение. Однако free () не signal safe function - поэтому я не должен это называть. Но как освободить () эту переменную?

Большое спасибо за ваши ответы ...

РЕДАКТИРОВАТЬ: valgrind также показывает переменную, которую можно переиграть:

==5928== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 15 from 1)
==5928== malloc/free: in use at exit: 20 bytes in 1 blocks.
==5928== malloc/free: 1 allocs, 0 frees, 20 bytes allocated.
==5928== For counts of detected errors, rerun with: -v
==5928== searching for pointers to 1 not-freed blocks.
==5928== checked 49,164 bytes.

Ответы [ 3 ]

4 голосов
/ 02 мая 2009

Я сомневаюсь, что вам нужно. Любая ОС, которая поддерживает fork (), также автоматически освобождает выделения из malloc () при выходе из процесса, независимо от того, как он это делает (включая завершение).

Существуют среды, в которых программы на С не запускаются в процессах, и где вы должны быть очень осторожны, чтобы не выходить из процесса на выходе. Но эти среды не POSIX и не будут поддерживать fork (). Они могут не поддерживать сигналы, в этом отношении. Если вы пишете для любой такой необычной среды, проверьте документацию ...

Если вы хотите увидеть чистый отчет valgrind, то вы можете сделать так, чтобы обработчик вставил событие в дочерний цикл событий (или установил флаг и опубликовал семафор или что-то еще) и обработал событие как чистый выход. Это также то, что вы сделали бы, если бы ваша программа была интерактивным приложением, и вы хотели сохранить данные пользователя на SIGTERM, при условии, что ваша структура пользовательского интерфейса еще не преобразовала SIGTERM в событие для вас.

0 голосов
/ 03 мая 2009

Вы можете использовать exec для запуска дочернего процесса из main вместо непосредственного вызова функции child (). Используйте аргумент командной строки, чтобы уведомить дочернюю программу о выполнении работы в main. Тогда дочерний процесс сможет правильно очиститься.

0 голосов
/ 02 мая 2009

Возможно, я что-то неправильно понимаю, но наверняка после SIGTERM весь процесс исчезнет, ​​забрав вашу переменную?

...