我使用PTRACE_SEIZE
来跟踪子流程的执行情况,但我遇到了一个非群组停靠问题PTRACE_EVENT_STOP
(signal == {当tracee收到SIGTRAP
时,会发出{1}})。我似乎无法找到任何可能表明这种情况发生的文档。根据我在SIGCONT
联机帮助页中收集的内容,ptrace(2)
仅在满足以下条件之一时才会出现:
PTRACE_EVENT_STOP
ptrace(PTRACE_INTERRUPT, ...)
,SIGSTOP
,SIGTSTP
或SIGTTIN
)SIGTTOU
/ fork
/ vfork
,跟踪器自动附加到新进程/线程在下面的示例程序中,我收到信号为clone
的{{1}},但它与这3个条件中的任何一个都不匹配。当我运行程序时,我得到以下输出:
PTRACE_EVENT_STOP
关于这个特定SIGTRAP
意味着什么的任何想法?
示例程序:
[Child] Raising SIGSTOP
Event for pid 29236: Tracee entered group-stop PTRACE_EVENT_STOP (signal: 19)
Event for pid 29236: Tracee entered non-group-stop PTRACE_EVENT_STOP (signal: 5)
Event for pid 29236: Tracee entered/exited syscall
Event for pid 29236: Tracee entered/exited syscall
Event for pid 29236: Tracee received signal (signal: 18)
Event for pid 29236: Tracee entered/exited syscall
[Child] Resumed from SIGSTOP
Event for pid 29236: Tracee entered/exited syscall
Event for pid 29236: Tracee entered/exited syscall
Event for pid 29236: Process exited
PTRACE_EVENT_STOP
似乎在看到非群组停靠#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <unistd.h>
static void handle_events(pid_t pid_spec)
{
while (1) {
int status;
pid_t pid = waitpid(pid_spec, &status, __WALL);
printf("Event for pid %d: ", pid);
if (WIFEXITED(status)) {
printf("Process exited\n");
break;
} else if (WIFSIGNALED(status)) {
printf("Process killed by signal\n");
break;
} else if (WIFSTOPPED(status)) {
int ptrace_event = status >> 16;
int signal = WSTOPSIG(status);
switch (ptrace_event) {
case PTRACE_EVENT_STOP:
if (signal == SIGSTOP || signal == SIGTSTP
|| signal == SIGTTIN || signal == SIGTTOU) {
printf("Tracee entered group-stop PTRACE_EVENT_STOP (signal: %d)\n", signal);
ptrace(PTRACE_LISTEN, pid, NULL, NULL);
} else {
printf("Tracee entered non-group-stop PTRACE_EVENT_STOP (signal: %d)\n", signal);
ptrace(PTRACE_SYSCALL, pid, NULL, 0);
}
break;
default:
if (signal == (SIGTRAP | 0x80)) {
printf("Tracee entered/exited syscall\n");
ptrace(PTRACE_SYSCALL, pid, NULL, 0);
} else {
printf("Tracee received signal (signal: %d)\n", signal);
ptrace(PTRACE_SYSCALL, pid, NULL, signal);
}
break;
}
}
}
}
int main()
{
pid_t pid = fork();
if (pid == 0) {
printf("[Child] Raising SIGSTOP\n");
// Allow parent to PTRACE_SEIZE
if (raise(SIGSTOP) != 0) {
_exit(255);
}
printf("[Child] Resumed from SIGSTOP\n");
_exit(0);
}
// Wait for stop
int status;
waitpid(pid, &status, WSTOPPED);
ptrace(PTRACE_SEIZE, pid, NULL, PTRACE_O_TRACESYSGOOD);
// Allow child to continue
kill(pid, SIGCONT);
handle_events(pid);
return EXIT_SUCCESS;
}
时就致电strace
:
答案 0 :(得分:1)
我设法找出事件发生的原因。
当某个流程与PTRACE_SEIZE
进行匹配时,ptrace_trap_notify()
会在set JOBCTL_TRAP_NOTIFY
或JOBCTL_TRAP_STOP
被设置时调用get_signal()
一个SIGCONT
is received。 JOBCTL_TRAP_MASK
会检查JOBCTL_TRAP_STOP | JOBCTL_TRAP_NOTIFY
(即<stopping signal> | (PTRACE_EVENT_STOP << 8)
)和stopping signal is received。如果进程进入群组停止,call do_jobctl_trap()
会发送SIGTRAP | (PTRACE_EVENT_STOP << 8)
,否则会发送PTRACE_SEIZE
。
因此,在使用<stopping signal> | (PTRACE_EVENT_STOP << 8)
:
SIGCONT
事件SIGTRAP | (PTRACE_EVENT_STOP << 8)
信号将导致class PgSplash(Screen):
def skip(self, dt):
screen.switch_to(pages[1])
def on_enter(self, *args):
Clock.schedule_once(self.skip, 5)
class PgBrowser(Screen):
def on_pre_enter(self, *args):
user_path = os.path.join(browser_base.get_home_directory(), 'Documents')
browser = browser_base.FileBrowser(select_string='Select',
favorites=[(user_path, 'Documents')])
browser.bind(on_success=self._fbrowser_success,
on_canceled=self._fbrowser_canceled,
on_submit=self._fbrowser_submit)
self.add_widget(browser)
def _fbrowser_canceled(self, instance):
print('cancelled, Close self.')
self.root_window.hide()
sys.exit(0)
def _fbrowser_success(self, instance): # select pressed
global file
print(instance.selection)
file = instance.selection[0]
def _fbrowser_submit(self, instance): # clicked on the file
global file
print(instance.selection)
file = instance.selection[0]
pages = [PgSplash(name="PgSplash"),
PgBrowser(name="PgBrowser")]
screen = ScreenManager()
screen.add_widget(pages[0])
class myApp(App):
def build(self):
screen.current = "PgSplash"
return screen
myApp().run()
事件此行为似乎已在do_jobctl_trap()
中引入。