2016-05-03 1:19 GMT+03:00 Mark Kettenis <mark.kette...@xs4all.nl>: >> 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;
I think you're right. I've modelled the kernel code after libkvm, and your suggestion makes it much easier to read, thanks! I'll send updated diff a bit later, have to close lid right now. Thanks! >> > 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; >> >> -- WBR, Vadim Zhukov