Skip to content
This repository has been archived by the owner on Sep 8, 2020. It is now read-only.

Linux kernel thread criteria is wrong #1001

Open
angelsl opened this issue May 9, 2020 · 3 comments
Open

Linux kernel thread criteria is wrong #1001

angelsl opened this issue May 9, 2020 · 3 comments

Comments

@angelsl
Copy link

angelsl commented May 9, 2020

It's possible for user tasks to have an empty cmdline too, if argv was NULL when it was exec-ed. (Rare, but it happens.)

The correct way to check for a kernel thread is to check if its parent PID is 2. Although this kind of is a kernel implementation detail, currently:

  1. kthreadd is guaranteed to be PID 2 because it is started right after init is created (but before init is scheduled)
  2. All kernel threads are created by (in-kernel) forking off kthreadd, so all kernel threads have PPID of kthreadd, which is 2.

Alternatively, you could check for zero vsize but not a zombie. (This is of course impossible for a userspace process.) (Credits to this SO answer for this.)

I'll make a PR if I have time.

@wangqr
Copy link
Contributor

wangqr commented May 22, 2020

It's possible for user tasks to have an empty cmdline too, if argv was NULL when it was exec-ed.

htop is using this method because it is also used by ps and top. See https://stackoverflow.com/a/12231039/3342190 .

The correct way to check for a kernel thread is to check if its parent PID is 2.

I could not find any document that guarentees this behavior. Plus, kthreadd only presents in linux 2.6+. See the link above ("On newer kernels (CentOS 6.x has 2.6.32) all kernel-threads seem to be a child of kthreadd. On older kernels (CentOS 5.x has 2.6.18) I see kernel-threads are a child of kthread (without the extra d) OR are a child of init.").

Even if we are dropping support for older kernels, there are better ways to do this: https://stackoverflow.com/a/56369641/3342190 . It is well documented, and works for 2.6+.

This PF_KTHREAD approach was actually discussed in #761, but eventually not accepted.

@angelsl
Copy link
Author

angelsl commented May 22, 2020

See https://stackoverflow.com/a/12231039/3342190.

This simply asserts that it is the method, but doesn't cite anything. I took a cursory glance through the source of procps-ng and I can't find any feature in ps and top that actually distinguishes kernel tasks from user tasks. The only relevant mention of this is in top's manpage, which says:

6. COMMAND -- Command Name or Command Line

Display the command line used to start a task or the name of the associated program. You toggle between command line and name with 'c', which is both a command-line option and an interactive command.

When you've chosen to display command lines, processes without a command line (like kernel threads) will be shown with only the program name in brackets, as in this example:

[kthreadd]

...which doesn't actually say that they distinguish kthreads from user threads, just that kthreads (having no cmdline) will be displayed like so.

I could not find any document that guarentees this behavior.

Indeed there isn't, though it has been this way ever since kthreadd was introduced. (v2.6.22) And I don't imagine this changing, because there is a reason it is PID 2—we want init to be PID 1, but kthreadd needs to be launched before init can actually start executing because init will do things that cause kthreads to be created. So we have to create init so it gets PID 1, and before scheduling init we create kthreadd. So kthreadd gets PID 2. There can be no user process that gets PID 2 because init isn't scheduled until kthreadd is created.

But yeah I agree, it's probably better to go with checking PF_KTHREAD. Since it is exposed in procfs, it is now userspace-visible behaviour, and with Linux's don't-break-userspace guarantees, we can rely on this behaviour.

For kernels < v2.6.27 (which we should check via uname or such) when PF_KTHREAD was introduced, then we can fall back to checking cmdline.

I don't think this current way of checking for kthread is correct anyway, because it is entirely possible for user threads to end up with a NULL cmdline. (That's the entire reason I stumbled upon this issue. I was confused for 10-15 minutes why some process appeared in top but not htop—which I usually set to hide kernel threads, and I didn't expect that to be the problem..)

@wangqr
Copy link
Contributor

wangqr commented May 22, 2020

For kernels < v2.6.27 (which we should check via uname or such) when PF_KTHREAD was introduced, then we can fall back to checking cmdline.

A check or switch will be great. It's here if you wan't to make a PR:
https://github.com/hishamhm/htop/blob/master/linux/LinuxProcessList.c#L695

KoffeinFlummi pushed a commit to KoffeinFlummi/htop-vim that referenced this issue Feb 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants