asmlinkage int px_sys_exit(int error_code)
{
	long ret = 0;
	/**
	 * We must save the original sys_exit function here. If the current pid
	 * is the application the user launched and user selected "stop sampling
	 * on application unload", then the function "enum_module_for_exit_check"
	 * will terminate the sampling session, which in turn will remove all the
	 * syscall hooks. On 2.4 kernel it is not going to happen, because the 
	 * utility has no chance to run until this function returns; but on 2.6
	 * kernel with preempt turned on, the utility maybe scheduled run before 
	 * the following call to px_original_sys_exit, so at that time the module
	 * tracker is already unloaded and the px_original_sys_exit becomes NULL
	 * pointer. The following px_sys_exit_group has the same situation.
	 */
	sys_exit_t saved_sys_exit = px_original_sys_exit;

	if (gb_enable_os_hooks) 
	{
		check_launched_app_exit(current->tgid);
	}

	ret = saved_sys_exit(error_code);

	return ret;
}
static int task_exit_notify(struct notifier_block *self, unsigned long val, void *data)
{
	struct task_struct * task = (struct task_struct *)data;
	
	if (gb_enable_os_hooks)
	{
		check_launched_app_exit(task->pid);
	}

	return 0;
}
asmlinkage long px_sys_kill(int pid, int sig)
{
	long ret = 0;
	sys_kill_t saved_sys_kill = px_original_sys_kill;

	ret = saved_sys_kill(pid, sig);
	
	if (!ret && gb_enable_os_hooks && is_kill_sig(sig))
	{
		check_launched_app_exit(pid);
	}

	return ret;
}
asmlinkage int px_sys_exit_group(int error_code)
{
	long ret = 0;

	sys_exit_group_t saved_sys_exit_group = px_original_sys_exit_group;

	if (gb_enable_os_hooks)
	{
		check_launched_app_exit(current->tgid);
	}
	
	ret = saved_sys_exit_group(error_code);

	return ret;
}