> Date: Tue, 3 May 2016 00:04:13 +0200
> From: Alexander Bluhm <[email protected]>
>
> On Sun, May 01, 2016 at 01:24:19AM +0300, Vadim Zhukov wrote:
> > When matching by PID, we'd better return ESRCH expicitly rather
> > than zero entries. This makes, for example, fstat(1) behaviour
> > more consistent and makes it easier to replace "if lsof -p ..."
> > checks in third-party code with "if fstat -p ...".
> >
> > For libkvm, I explicitly test for ESRCH to avoid going inside
> > kmem without real need.
> >
> > Tested on amd64.
> >
> > Comments? Okays?
>
> Your use case makes sense. So I think this should go in.
The code change is abit convoluted though though. It's enough to
initialize matched to 0 before the LIST_FOREACH and set it
unconditionally to after the
if (arg > 0 && pr->ps_pid != (pid_t)arg)
check. So:
matched = 0
LIST_FOREACH(pr, &allprocess, ps_list) {
/*
* skip system, exiting, embryonic and undead
* processes
*/
if (pr->ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING))
continue;
if (arg > 0 && pr->ps_pid != (pid_t)arg) {
/* not the pid we are looking for */
continue;
}
matched = 1;
> > Index: sys/kern/kern_sysctl.c
> > ===================================================================
> > RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
> > retrieving revision 1.300
> > diff -u -p -r1.300 kern_sysctl.c
> > --- sys/kern/kern_sysctl.c 29 Feb 2016 19:44:07 -0000 1.300
> > +++ sys/kern/kern_sysctl.c 30 Apr 2016 22:26:06 -0000
> > @@ -1225,7 +1225,7 @@ sysctl_file(int *name, u_int namelen, ch
> > struct process *pr;
> > size_t buflen, elem_size, elem_count, outsize;
> > char *dp = where;
> > - int arg, i, error = 0, needed = 0;
> > + int arg, i, error = 0, needed = 0, matched;
> > u_int op;
> > int show_pointers;
> >
> > @@ -1325,6 +1325,7 @@ sysctl_file(int *name, u_int namelen, ch
> > error = EINVAL;
> > break;
> > }
> > + matched = (arg <= 0);
> > LIST_FOREACH(pr, &allprocess, ps_list) {
> > /*
> > * skip system, exiting, embryonic and undead
> > @@ -1332,9 +1333,12 @@ sysctl_file(int *name, u_int namelen, ch
> > */
> > if (pr->ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING))
> > continue;
> > - if (arg > 0 && pr->ps_pid != (pid_t)arg) {
> > - /* not the pid we are looking for */
> > - continue;
> > + if (arg > 0) {
> > + /* is this the pid we are looking for? */
> > + if (pr->ps_pid == (pid_t)arg)
> > + matched = 1;
> > + else
> > + continue;
> > }
> > fdp = pr->ps_fd;
> > if (pr->ps_textvp)
> > @@ -1353,6 +1357,8 @@ sysctl_file(int *name, u_int namelen, ch
> > FILLIT(fp, fdp, i, NULL, pr);
> > }
> > }
> > + if (!matched)
> > + error = ESRCH;
> > break;
> > case KERN_FILE_BYUID:
> > LIST_FOREACH(pr, &allprocess, ps_list) {
> > Index: lib/libkvm/kvm_file2.c
> > ===================================================================
> > RCS file: /cvs/src/lib/libkvm/kvm_file2.c,v
> > retrieving revision 1.47
> > diff -u -p -r1.47 kvm_file2.c
> > --- lib/libkvm/kvm_file2.c 4 Sep 2015 02:58:14 -0000 1.47
> > +++ lib/libkvm/kvm_file2.c 30 Apr 2016 22:26:06 -0000
> > @@ -149,7 +149,7 @@ kvm_getfiles(kvm_t *kd, int op, int arg,
> > /* find size and alloc buffer */
> > rv = sysctl(mib, 6, NULL, &size, NULL, 0);
> > if (rv == -1) {
> > - if (kd->vmfd != -1)
> > + if (errno != ESRCH && kd->vmfd != -1)
> > goto deadway;
> > _kvm_syserr(kd, kd->program, "kvm_getfiles");
> > return (NULL);
> > @@ -266,7 +266,7 @@ kvm_deadfile_byid(kvm_t *kd, int op, int
> > {
> > size_t buflen;
> > struct nlist nl[4], *np;
> > - int n = 0;
> > + int n = 0, matched = 0;
> > char *where;
> > struct kinfo_file kf;
> > struct file *fp, file;
> > @@ -312,6 +312,9 @@ kvm_deadfile_byid(kvm_t *kd, int op, int
> > kd->filebase = (void *)where;
> > buflen = (nfiles + 10) * esize;
> >
> > + if (op != KERN_FILE_BYPID || arg <= 0)
> > + matched = 1;
> > +
> > for (pr = LIST_FIRST(&allprocess);
> > pr != NULL;
> > pr = LIST_NEXT(&process, ps_list)) {
> > @@ -333,10 +336,12 @@ kvm_deadfile_byid(kvm_t *kd, int op, int
> > goto cleanup;
> > }
> >
> > - if (op == KERN_FILE_BYPID && arg > 0 &&
> > - proc.p_pid != (pid_t)arg) {
> > - /* not the pid we are looking for */
> > + if (op == KERN_FILE_BYPID) {
> > + /* check if this is the pid we are looking for */
> > + if (arg > 0 && proc.p_pid != (pid_t)arg)
> > continue;
> > + else
> > + matched = 1;
> > }
> >
> > if (KREAD(kd, (u_long)process.ps_ucred, &ucred)) {
> > @@ -457,6 +462,10 @@ kvm_deadfile_byid(kvm_t *kd, int op, int
> > buflen -= esize;
> > n++;
> > }
> > + }
> > + if (!matched) {
> > + errno = ESRCH;
> > + goto cleanup;
> > }
> > done:
> > *cnt = n;
>
>