Rationale for setting COMMLEN to 19 in struct kinfo_proc
Gleb Popov
arrowd at freebsd.org
Fri Jun 1 11:45:12 UTC 2018
On Wed, May 30, 2018 at 5:10 AM, John Baldwin <jhb at freebsd.org> wrote:
>
> --
> John Baldwin
> On 5/29/18 8:16 PM, Brooks Davis wrote:
> > On Tue, May 29, 2018 at 11:42:47PM +0300, Gleb Popov wrote:
> >> Hello.
> >>
> >> I've been debugging a failing Qt (KDE, to be precise) test and found
> that
> >> process name returned in kinfo_proc structure gets truncated to 19
> symbols.
> >> This causes other errors in the application. I'm wondering why is this
> >> field so small and is there possibility to increase it? I think, having
> >> applications with names longer than 19 characters is not that rare.
> >>
> >> Relevant header: /usr/include/sys/user.h
> >>
> >> Simple testcase to feature the problem:
> >>
> >> # cat k.cpp
> >> #include <sys/types.h>
> >> #include <signal.h>
> >> #include <unistd.h>
> >> #include <stdio.h>
> >>
> >> #include <sys/cdefs.h>
> >> #include <sys/param.h>
> >> #include <sys/sysctl.h>
> >> #include <sys/user.h>
> >>
> >> int main()
> >> {
> >> auto pid = getpid();
> >> struct kinfo_proc kp;
> >> int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid };
> >>
> >> size_t len = sizeof(kp);
> >> u_int mib_len = sizeof(mib)/sizeof(u_int);
> >>
> >> if (sysctl(mib, mib_len, &kp, &len, NULL, 0) < 0)
> >> return -1;
> >>
> >> puts(kp.ki_tdname);
> >> puts(kp.ki_comm);
> >>
> >> return 0;
> >> }
> >> # c++ -o abcdefghijklmnopqrstuvwxyz
> >> # ./abcdefghijklmnopqrstuvwxyz
> >> abcdefghijklmnop
> >> abcdefghijklmnopqrs
> >
> > Changing the size of fields in kinfo_proc would be enormously
> > disruptive. Take a look at all the source that uses KERN_PROC_PID for a
> > subset of things that would break.
> >
> > Sometimes we can break these interfaces, but I think this one would
> > require new sysctl mibs. If we did that we should come up with an
> > interface that is identical between 32-bit and 32-bit systems and
> > doesn't export pointers.
>
> p_comm[] in struct proc is only 20 bytes long (19 chars + nul), so you
> can't make it bigger in kinfo_proc anyway as we only store 19 chars
> in the kernel. (Note that we do have room to grow char arrays if
> needed without having to completely rototill though; we use a hack to
> store the "rest" of the thread name in a separate array to export the
> full 19 chars of the thread name now.)
>
> If you want the raw command line you can't get that via kinfo_proc.
> You can use the kern.proc.args sysctl or wrapper functions like
> kvm_getargv() or procstat_getargv(). You can then use argv[0] as the
> command name instead.
>
Thanks for your suggestion. I've tried that out and it does seem to work.
However, I'm slightly confused by the fact that procstat_getargv() returns
only command name and not the whole argv line, as function's name suggests.
Here is my code:
int main(int argc, char* argv[])
{
kvm_t * kvm = kvm_open(nullptr, "/dev/null", nullptr, O_RDONLY, "");
int cnt;
struct kinfo_proc * kp = kvm_getprocs(kvm, KERN_PROC_PID, getpid(),
&cnt);
struct procstat * ps = procstat_open_sysctl();
char ** argv0 = procstat_getargv(ps, kp, 0);
puts(*argv0);
procstat_close(ps);
kvm_close(kvm);
return 0;
}
Running "veryveryverylongcommandname" correctly produces
"veryveryverylongcommandname" line on stdout, but
"veryveryverylongcommandname args args args" also gives only
"veryveryverylongcommandname". Is this correct behavior or am I missing
something?
> --
> John Baldwin
> _______________________________________________
> freebsd-arch at freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/freebsd-arch
> To unsubscribe, send any mail to "freebsd-arch-unsubscribe at freebsd.org"
>
More information about the freebsd-arch
mailing list