> Date: Tue, 3 May 2016 00:04:13 +0200 > From: Alexander Bluhm <alexander.bl...@gmx.net> > > 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; > >