Discussion:
Rationale for setting COMMLEN to 19 in struct kinfo_proc
Gleb Popov
2018-05-29 20:42:47 UTC
Permalink
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
Brooks Davis
2018-05-30 00:16:38 UTC
Permalink
Post by Gleb Popov
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
# 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.

-- Brooks
John Baldwin
2018-05-30 02:10:39 UTC
Permalink
--
John Baldwin
Post by Brooks Davis
Post by Gleb Popov
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
# 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.
--
John Baldwin
Gleb Popov
2018-06-01 11:44:34 UTC
Permalink
Post by John Baldwin
--
John Baldwin
Post by Brooks Davis
Post by Gleb Popov
Hello.
I've been debugging a failing Qt (KDE, to be precise) test and found
that
Post by Brooks Davis
Post by Gleb Popov
process name returned in kinfo_proc structure gets truncated to 19
symbols.
Post by Brooks Davis
Post by Gleb Popov
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
# 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?
Post by John Baldwin
--
John Baldwin
_______________________________________________
https://lists.freebsd.org/mailman/listinfo/freebsd-arch
Konstantin Belousov
2018-06-01 13:41:47 UTC
Permalink
Post by Gleb Popov
Post by John Baldwin
--
John Baldwin
Post by Brooks Davis
Post by Gleb Popov
Hello.
I've been debugging a failing Qt (KDE, to be precise) test and found
that
Post by Brooks Davis
Post by Gleb Popov
process name returned in kinfo_proc structure gets truncated to 19
symbols.
Post by Brooks Davis
Post by Gleb Popov
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
# 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.
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.
Post by Gleb Popov
Post by John Baldwin
--
John Baldwin
_______________________________________________
https://lists.freebsd.org/mailman/listinfo/freebsd-arch
_______________________________________________
https://lists.freebsd.org/mailman/listinfo/freebsd-arch
Loading...