Craig Small schrob:
> Hi Jan,
>   The issue is that the command name is increasing in length in the kernel.
> So the utilities needed to increase their command name length as well.
> 
> ps -o comm <PID>
> 
> Would show you the field it's trying to match against and unless you have a
> very recent kernel it will be truncated to 16 characters.

Yes, I was aware of that limitation¹. I just think killall (and pgrep,
tbh) should handle that, so I don't have to count letters when I'm typing
into my shell, and can write shellscripts that work regardless of what
the kernel limit is.
And I think it's a good thing that the kernel is increasing that limit.
(To what? And might we even get another increase in the very far
future?)

> However leaving psmisc alone is not the answer either because when you do
> eventually get a newer kernel, the matching will fail again because you
> will have no way of specifying names longer than 16 characters.

Agreed, that's not a satisfactory outcome.

> Strictly speaking killall is working correctly. You're specifying a name
> longer than 16 characters and the process command name is trucated to 16
> characters so it's not a match. It is a bit annoying and unexpected though.

Well, even more strictly speaking killall(1) documents the --exact
switch to enable the behaviour you describe, and explains that without
that switch and with the whole command name unavailable, "killall will
kill everything that matches within the first 15 characters." So at the
very least the documentation is wrong now. ;-P

I guess the kernel doesn't export the length limit (TASK_COMM_LEN)
somehow? What if killall tries to set its own comm field to something
very large, reads it back and takes the length of that? (If that is
expensive, then do it only if the command name is a prefix of the given
name.)

Because once you know the kernel limit, you can just truncate the given
name to that length and compare.

> An idea I have been toying with is to check if the command name are exactly
> 16 characters and the given name is 16 characters or more and match the
> first 16 as well.
> That way it's going to sort of conditionally work like before. I'll need to
> think about false positives and the most efficient way of doing it but that
> could solve things I think.

Well, false positives in your scheme can not occur on old kernels,
because everything is <=16 chars anyway.
And on new kernels, they occur iff the command name is truly 16 chars,
and a prefix of the given name. And if that situation had happened on an
old kernel, you'd have decided to kill the process, too!
So I don't think there's a way that scheme can break setups that worked
on old kernels. Worst case, you fail to take advantage of the additional
info the new kernel gives you.

About efficiency, I think figuring out whether A is a equal to B, a
proper prefix of B, or neither (and returning the length of A in the
2nd case) needn't be more expensive than strcmp²:
    while ( *a != '\0' && *b != '\0' && *a == *b) {
        ++a;
        ++b;
    }
    /* inspect *a and *b and return appropriately */
And in the proper prefix case, you can compare the length to
TASK_COMM_LEN (if you can figure it out), or 16 (your scheme) and that's
it.

Does that sound reasonable?
regards,
    Jan


¹ except that there's apparently some confusion about whether those 16
characters include the terminating nul. proc(5) and you seem to think
it doesn't, killall(1) and my kernel seem to think it does. :D

² well, strcmp might be carefully hand-optimized assembler code. But
since we're comparing strings of length ~16, I think we can manage
without that. ;)

Attachment: signature.asc
Description: PGP signature

Reply via email to