Linux - KernelThis forum is for all discussion relating to the Linux kernel.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Hi,
Going through the source code of 4.12
I cant wrap my head around the below code when task is being ptraced
do_wait()
... will call ptrace_do_wait(wo, tsk)
this will call wait_consider_task for every thread that it is tracing on
This will in turn call wait_task_stopped
This will then find the PID [pid = task_pid_vnr(p);] which is what waitpid will return
but then it calls put_task_struct(p); this will collect the free the task,
If that happens , then how does debugger wait on this process/task again?
What exact files? Whatever you posted is not seemingly code or vastly incomplete. Sorry, but no one can explain random pieces without a better idea of what files and more details what you're asking about. If this does have to do with kernel 4.12 I'd recommend you have this question moved to the Linux Kernel forum.
Not knowing the answer, however looking at the code reference, much thanks.
You are talking about the following clip:
Code:
static long do_wait(struct wait_opts *wo)
{
struct task_struct *tsk;
int retval;
trace_sched_process_wait(wo->wo_pid);
init_waitqueue_func_entry(&wo->child_wait, child_wait_callback);
wo->child_wait.private = current;
add_wait_queue(¤t->signal->wait_chldexit, &wo->child_wait);
repeat:
/*
* If there is nothing that can match our critiera just get out.
* We will clear ->notask_error to zero if we see any child that
* might later match our criteria, even if we are not able to reap
* it yet.
*/
wo->notask_error = -ECHILD;
if ((wo->wo_type < PIDTYPE_MAX) &&
(!wo->wo_pid || hlist_empty(&wo->wo_pid->tasks[wo->wo_type])))
goto notask;
set_current_state(TASK_INTERRUPTIBLE);
read_lock(&tasklist_lock);
tsk = current;
do { // Line 1489
retval = do_wait_thread(wo, tsk); // Line 1490
if (retval) // Line 1491
goto end; // Line 1492
// Line 1493
retval = ptrace_do_wait(wo, tsk); // Line 1494
if (retval) // Line 1495
goto end; // Line 1496
// Line 1497
if (wo->wo_flags & __WNOTHREAD) // Line 1498
break; // Line 1499
} while_each_thread(current, tsk); // Line 1500
read_unlock(&tasklist_lock);
notask:
retval = wo->notask_error;
if (!retval && !(wo->wo_flags & WNOHANG)) {
retval = -ERESTARTSYS;
if (!signal_pending(current)) {
schedule();
goto repeat;
}
}
end:
__set_current_state(TASK_RUNNING);
remove_wait_queue(¤t->signal->wait_chldexit, &wo->child_wait);
return retval;
}
SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
infop, int, options, struct rusage __user *, ru)
{
struct wait_opts wo;
struct pid *pid = NULL;
enum pid_type type;
long ret;
if (options & ~(WNOHANG|WNOWAIT|WEXITED|WSTOPPED|WCONTINUED))
return -EINVAL;
if (!(options & (WEXITED|WSTOPPED|WCONTINUED)))
return -EINVAL;
switch (which) {
case P_ALL:
type = PIDTYPE_MAX;
break;
case P_PID:
type = PIDTYPE_PID;
if (upid <= 0)
return -EINVAL;
break;
case P_PGID:
type = PIDTYPE_PGID;
if (upid <= 0)
return -EINVAL;
break;
default:
return -EINVAL;
}
if (type < PIDTYPE_MAX)
pid = find_get_pid(upid);
wo.wo_type = type;
wo.wo_pid = pid;
wo.wo_flags = options;
wo.wo_info = infop;
wo.wo_stat = NULL;
wo.wo_rusage = ru;
ret = do_wait(&wo);
if (ret > 0) {
ret = 0;
} else if (infop) {
/*
* For a WNOHANG return, clear out all the fields
* we would set so the user can easily tell the
* difference.
*/
if (!ret)
ret = put_user(0, &infop->si_signo);
if (!ret)
ret = put_user(0, &infop->si_errno);
if (!ret)
ret = put_user(0, &infop->si_code);
if (!ret)
ret = put_user(0, &infop->si_pid);
if (!ret)
ret = put_user(0, &infop->si_uid);
if (!ret)
ret = put_user(0, &infop->si_status);
}
put_pid(pid);
return ret;
}
There is a do-while loop from lines 1489 through 1500. This continues through the list of tasks.
I realize that you are reading into the do_wait_thread() call and the ptrace_do_wait() call. They are not my area of expertise, however my impression would be that the author of the ptrace_do_wait() would wish to do not harm to any list of processes, so that the loop would continue, and also the outcome of the do_wait_thread() call leaves things in place for the ptrace call. Further, the ptrace_do_wait() should fairly mirror the do_wait_thread() as far as decoding, but not change anything, and instead record the event as it is designed to do. I tend to add printk() calls to verify things like this when tracing the kernel.
Moved: This thread is more suitable in the Linux Kernel forum and has been moved accordingly to help your thread/question get the exposure it deserves.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.