Прежде всего позвольте мне предсказать, что Я понимаю, почему не входящие функции могут вызвать взаимоблокировку в обработчике сигналов, однако я не могу вызвать проблему независимо от того, как сильно я стараюсь.
У меня есть моя первая программа, запускающая 1024 malloc и printfs каждый сигнал, и у меня есть несколько других программ, запущенных с 2 потоками на сигналы запуска программы в первый раз, и даже после запуска их в течение получаса подряд я не вижу тупиков.
Я собираю и запускаю эти программы на 64-битной Ubuntu 14.04.5 LTS (Trusty) с помощью gcc (Ubuntu 4.8.4-2ubuntu1 ~ 14.04.4) 4.8.4.
Первая программа (та, которая должнаdeadlock is) is:
// victim.c
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
// global arr to put our malloc results to avoid
// compiler doing any funny business and optimizing
// away the malloc calls, not sure if this is really
// actually necessary or not
void *arr[1024];
// sigint handler to do bad stuff in a loop
void inthandler(int sig)
{
int i = 0;
for (i = 0; i < 1024; ++i) {
// some printf
printf("Signal loop %d\n", i);
if (arr[i]) free(arr[i]);
arr[i] = malloc(1024);
}
}
void main(void)
{
// clear out our arr
memset(arr, 0, sizeof(arr));
// install our sigint handler
signal(SIGINT, inthandler);
// loop and wait for signals
while (1) {}
}
И я скомпилирую его с (O0, чтобы быть явно, что мы не оптимизируем):
gcc ./victim.c -O0 -o victim
Затем «убийца», то есть программа, отправляющаяСигналы, которые должны в конечном итоге вызвать тупик у жертвы, выглядят следующим образом:
// killer.c
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
// hack to grab pid of victim
static pid_t __grab_victim_pid()
{
char line[1024] = {0};
FILE *command = NULL;
pid_t pid = 0;
printf("Getting pid of victim...\n");
do {
command = popen("pidof victim", "r");
memset(line, 0, sizeof(line));
fgets(line, sizeof(line) - 1, command);
pid = strtoul(line, NULL, 10);
pclose(command);
} while (pid == 0);
printf("Grabbed pid of victim: [%u]\n", pid);
return pid;
}
static void *__loop_threadfunc(void *param)
{
pid_t pid = 0;
size_t i = 0;
pid = __grab_victim_pid();
while (1) {
kill(pid, SIGINT);
}
return 0;
}
int main(int argc, char *argv[])
{
pthread_t thread1;
pthread_t thread2;
// Spawn the threads
if (pthread_create(&thread1, NULL, __loop_threadfunc, NULL) != 0 ||
pthread_create(&thread2, NULL, __loop_threadfunc, NULL) != 0) {
fprintf(stderr, "Failed to create a thread\n");
return 1;
}
// join the threads to wait for them
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
Скомпилировано с:
gcc ./killer.c -O0 -o killer -lpthread
И затем я запускаю процесс жертвы в одном терминале, перепрыгиваю надругой терминал и запускает несколько фоновых процессов-убийц; естественно, процесс-жертва выплевывает множество строк для вывода из каждого полученного сигнала, но он никогда не блокируется ...
Кроме того, выпадающие линии всегдапо порядку, то есть сообщения «Цикл сигнала% d» никогда не прерываются, что указывает на то, что сигнал никогда не доставляется в середине выполнения активного обработчика сигнала.Кажется, это идет вразрез с тем, что все говорят об обработчиках сигналов.
Я что-то не так делаю?Мне просто очень повезло?Или, может быть, моя ОС защищена от этой проблемы (это вообще возможно)?
Я пытался прикрепить strace к жертве, и я вижу, что он всегда сообщает rt_sigreturn, а затем последующий SIGINT в паре:
rt_sigreturn() = 0
--- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=11564, si_uid=0} ---
Я мог бы представить, что "SIGINT" должен бытьдоставляется до rt_sigreturn (до того, как он существует из обработчика сигнала), но этого, кажется, никогда не происходит, он выглядит , как будто процесс блокирует SIGINT до тех пор, пока текущий обработчик сигнала не завершится ... (Это может 'не так ли, правда?)
Заранее спасибо, любые разъяснения по этому поводу были бы очень благодарны!
Edit1: я оставил 10 процессов-убийц, работающих на одном процессе-жертве, будет публиковать результаты, есличто-нибудь происходит.
Edit2: Может ли это иметь какое-либо отношение к тому факту, что я запускаю эти тесты на виртуальной машине?