Пример #1
0
void
handle_event(Event *event) {
	if (exiting == 1) {
		exiting = 2;
		debug(1, "ltrace about to exit");
		ltrace_exiting();
	}
	debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)",
	      event->proc ? event->proc->pid : -1, event->type);

	/* If the thread group or an individual task define an
	   overriding event handler, give them a chance to kick in.
	   We will end up calling both handlers, if the first one
	   doesn't sink the event.  */
	if (event->proc != NULL) {
		event = call_handler(event->proc, event);
		if (event == NULL)
			/* It was handled.  */
			return;

		/* Note: the previous handler has a chance to alter
		 * the event.  */
		if (event->proc != NULL
		    && event->proc->leader != NULL
		    && event->proc != event->proc->leader) {
			event = call_handler(event->proc->leader, event);
			if (event == NULL)
				return;
		}
	}

	switch (event->type) {
	case EVENT_NONE:
		debug(1, "event: none");
		return;
	case EVENT_SIGNAL:
		debug(1, "event: signal (%s [%d])",
		      shortsignal(event->proc, event->e_un.signum),
		      event->e_un.signum);
		handle_signal(event);
		return;
	case EVENT_EXIT:
		debug(1, "event: exit (%d)", event->e_un.ret_val);
		handle_exit(event);
		return;
	case EVENT_EXIT_SIGNAL:
		debug(1, "event: exit signal (%s [%d])",
		      shortsignal(event->proc, event->e_un.signum),
		      event->e_un.signum);
		handle_exit_signal(event);
		return;
	case EVENT_SYSCALL:
		debug(1, "event: syscall (%s [%d])",
		      sysname(event->proc, event->e_un.sysnum),
		      event->e_un.sysnum);
		handle_syscall(event);
		return;
	case EVENT_SYSRET:
		debug(1, "event: sysret (%s [%d])",
		      sysname(event->proc, event->e_un.sysnum),
		      event->e_un.sysnum);
		handle_sysret(event);
		return;
	case EVENT_ARCH_SYSCALL:
		debug(1, "event: arch_syscall (%s [%d])",
				arch_sysname(event->proc, event->e_un.sysnum),
				event->e_un.sysnum);
		handle_arch_syscall(event);
		return;
	case EVENT_ARCH_SYSRET:
		debug(1, "event: arch_sysret (%s [%d])",
				arch_sysname(event->proc, event->e_un.sysnum),
				event->e_un.sysnum);
		handle_arch_sysret(event);
		return;
	case EVENT_CLONE:
	case EVENT_VFORK:
		debug(1, "event: clone (%u)", event->e_un.newpid);
		handle_clone(event);
		return;
	case EVENT_EXEC:
		debug(1, "event: exec()");
		handle_exec(event);
		return;
	case EVENT_BREAKPOINT:
		debug(1, "event: breakpoint");
		handle_breakpoint(event);
		return;
	case EVENT_NEW:
		debug(1, "event: new process");
		handle_new(event);
		return;
	default:
		fprintf(stderr, "Error! unknown event?\n");
		exit(1);
	}
}
Пример #2
0
int handle_event(struct task *task)
{
	int ret;

	if (!task)
		return 0;

	debug(DEBUG_EVENT, "+++ process pid=%d event: %d", task->pid, task->event.type);

	assert(task->stopped);

	if (task->defer_func) {
		ret = task->defer_func(task, task->defer_data);

		if (ret == RET_DELETED)
			return 1;

		task->defer_func = NULL;
		task->defer_data = NULL;
		goto out2;
	}

	struct event *event = &task->event;
	enum event_type type = event->type;

	switch (type) {
	case EVENT_NONE:
		ret = continue_task(task, task->event.e_un.signum);
		break;
	case EVENT_SIGNAL:
		ret = handle_signal(task);
		break;
	case EVENT_ABOUT_EXIT:
		ret = handle_about_exit(task);
		goto out1;
	case EVENT_EXIT:
		ret = handle_exit(task);
		break;
	case EVENT_EXIT_SIGNAL:
		ret = handle_exit_signal(task);
		break;
	case EVENT_FORK:
	case EVENT_VFORK:
	case EVENT_CLONE:
		ret = handle_child(task);
		break;
	case EVENT_EXEC:
		ret = handle_exec(task);
		break;
	case EVENT_BREAKPOINT:
		ret = handle_breakpoint(task);
		goto out2;
	case EVENT_NEW:
		ret = handle_new(task);
		break;
	default:
		fprintf(stderr, "fatal error, unknown event %d\n", type);
		abort();
	}

	if (ret == RET_DELETED)
		return 1;

	if (ret != RET_DEFERED) {
		assert(task->event.type == EVENT_NONE);
		assert(task->stopped == 0);
	}
out2:
	assert(task->is_new == 0);
out1:
	return (ret < 0) ? ret : 0;
}