Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 1 Jun 2018 16:41:47 +0300
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        Gleb Popov <arrowd@freebsd.org>
Cc:        John Baldwin <jhb@freebsd.org>, freebsd-arch@freebsd.org
Subject:   Re: Rationale for setting COMMLEN to 19 in struct kinfo_proc
Message-ID:  <20180601134147.GB3789@kib.kiev.ua>
In-Reply-To: <CALH631mvictRqAp1LfTsdzKe9O68MnZN1Wx4nFcZq8Y%2BKRwc7g@mail.gmail.com>
References:  <CALH631=XtWUMZnrz8%2BOH57GgY07pDY2du9OEOna6Pcd-zF=S8Q@mail.gmail.com> <20180530001638.GN99063@spindle.one-eyed-alien.net> <6cdb7530-b689-7666-7ce4-9b91acfc6255@FreeBSD.org> <CALH631mvictRqAp1LfTsdzKe9O68MnZN1Wx4nFcZq8Y%2BKRwc7g@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Jun 01, 2018 at 02:44:34PM +0300, Gleb Popov wrote:
> On Wed, May 30, 2018 at 5:10 AM, John Baldwin <jhb@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?
You do not print argv[1] etc, so they are not printed.
Note that availabitily of the argv and env is optional, the data can
be missed for many reasons.  Kernel is guaranteed to see it only
during execve(2), not between.

> 
> 
> > --
> > John Baldwin
> > _______________________________________________
> > freebsd-arch@freebsd.org mailing list
> > https://lists.freebsd.org/mailman/listinfo/freebsd-arch
> > To unsubscribe, send any mail to "freebsd-arch-unsubscribe@freebsd.org"
> >
> _______________________________________________
> freebsd-arch@freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/freebsd-arch
> To unsubscribe, send any mail to "freebsd-arch-unsubscribe@freebsd.org"



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20180601134147.GB3789>