LINUX.ORG.RU

ptrace() и сигналы

 , , ,


0

1

Здравсте!

Не проходят сигналы приложению при трассировке. Те не вызывается обработчик в трассируемом приложении:

sigtest.c:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <syscall.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>

void sig_handler(int signum) {
	write(1,"SIG\n",4);
	sleep(1);
}

void main() {
	signal(15, sig_handler);
	sleep(20);
	return;
}

dbgr.c:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <syscall.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <sys/user.h>
#include <inttypes.h>

int main(int argnum,char ** args) {
	int pid=atoi(args[1]);
	ptrace(PTRACE_ATTACH,pid, 0, 0);
	
	struct user_regs_struct regs;
	int wait_stat; 
	int rsig;
	 
	waitpid(pid,&wait_stat,0);
	while (WIFSTOPPED(wait_stat)) {
		ptrace(PTRACE_GETREGS,pid, 0,&regs);
		
		rsig=WSTOPSIG(wait_stat);
		dprintf(2," \n %d %"PRIx64"\n",rsig,regs.rip);
	
		if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0) {perror("ptrace_singlestep"); return -1;};
		waitpid(pid,&wait_stat,0);
	}

}

Если запустить sigtest и в течении 20 секунд подключится к нему через dbgr, а затем отправить сигнал 15 процессу sigtest, то он его проигнорирует, хотя dbgr выведет сообщение

5 7fc478feb2f0
 
15 7fc478feb2f0
.

Собственно вопрос: как можно пропустить сигнал в приложение, не останавливая трассировку?

Signal injection and suppression After signal-delivery-stop is observed by the tracer, the tracer should restart the tracee with the call

ptrace(PTRACE_restart, pid, 0, sig)

where PTRACE_restart is one of the restarting ptrace requests. If sig is 0, then a signal is not delivered. Otherwise, the signal sig is delivered. This operation is called signal injection in this manual page, to distinguish it from signal-delivery-stop.

anonymous ()
Ответ на: комментарий от anonymous

Как то я всеровно не понял логику работы.

Нпример если запустить dbgr, но sigtest вызвать через traceme и exec в dbgr, то сигналы будут игнорироваться не только трассировщиком, но и трассируемым процессом.

cyber_eagle ()
Ответ на: комментарий от cyber_eagle

Тебе написали же чёрным по белому: сигналы, перехваченные отладчиком, надо возвращать обратно в отлаживаемый процесс. Для этого их номер передаётся последним аргументом ptrace(). Это работает для всех операций, возобновляющих исполнение остановленного процесса (PTRACE_CONT, PTRACE_SINGLESTEP, и т. д.)

ilammy ★★★ ()
Ответ на: комментарий от ilammy

dbgr.c:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <syscall.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <sys/user.h>
#include <inttypes.h>

int main(int argnum,char ** args) {
	int pid;
	struct user_regs_struct regs;
	int wait_stat; 
	int rsig;
	
	switch (pid = fork()) {
	    case -1: break;
	    case 0: 
			ptrace(PTRACE_TRACEME, 0, 0, 0);
			if(execl(args[1],"",NULL)!=0) {perror("execl");}
			break;
	          
		default:
			waitpid(pid,&wait_stat,0);
			while (WIFSTOPPED(wait_stat)) {
				ptrace(PTRACE_GETREGS,pid, 0,&regs);
				
				rsig=WSTOPSIG(wait_stat);
				dprintf(2," \n %d %"PRIx64"\n",rsig,regs.rip);
			
				if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0) {perror("ptrace_singlestep"); return -1;};
				waitpid(pid,&wait_stat,0);
			}
	    }
	return 0;
}

#./dbgr.out sigtest.out
В этом случае сигнал 15 будет проигнорирован трассировщиком. Почему? Чем это отличается от варианта с ptrace attach?

Почему трассировщик, при таком варианте загрузки дочернего процесса, не получает сигналы?

cyber_eagle ()
Ответ на: комментарий от cyber_eagle

После отправки сигнала в выводе вот что:

 5 7fa1bcd892e9
 
 5 7fa1bcd892ee
                  #на этом моменте я отправил сигнал
Завершено

Те сигнал не обработал ни трасировщик, ни дочерний процесс...

cyber_eagle ()