Ouch! Should have looked at the jpilst arguments.
You know, the people in Nashua take bugs in system calls pretty seriously.
Can we reproduce this? If so, by all means, I'll report it!
> -----Original Message-----
> From: Craig A. Berry [mailto:[EMAIL PROTECTED]]
> Sent: Monday, July 24, 2000 8:17 PM
> To: Jordan Henderson
> Cc: [EMAIL PROTECTED]
> Subject: Perl hang again (was RE: testing Perl)
>
>
> At 05:51 PM 7/24/00 -0400, Jordan Henderson wrote:
> >If I may speak for Craig, I think he was suggesting that there be a
> >counter set before the loop and incremented in the loop to
> see if this
> >loop has been executed some unreasonable number of times and aborting
> >when this is detected.
>
> Yes, that was the idea. It wouldn't create a workable
> situation out of an
> unworkable one, but it would be better to get an unexplained
> abort than
> to loop forever in kernel mode, allocating another chunk of
> memory at each
> iteration.
>
> >But, that doesn't seem to be a good suggestion. As we can see from
> >inspection and from the attached debugging that Anders
> Wallin performed,
> >the rlen/rsiz are never changed in the loop. This loop is
> clearly bogus,
> >so why bother counting the number of times it will loop
> invalidly? As
> >it stands, this code will always loop infinitely when (rlen
> < rsiz) is
> >true on entry (or abort from an eventual getjpi() status error).
> >
> >This loop should be avoided, not aborted! Now, granted, there may be
> >a case that's being missed here (when all the identifiers weren't
> >gotten in the first pass), but this loop is no solution.
>
> Jordan, welcome to the club of those who have read the code
> incorrectly.
> The loop only appears to have no exit strategy, and indeed
> when looking only
> at the loop by itself it's hard to see how rlen or rsz could
> ever change
> within it:
>
> while (rlen < rsz) {
> /* We didn't get all the identifiers on the first pass.
> Allocate a
> * buffer much larger than $GETJPI wants (rsz is size
> in bytes that
> * were needed to hold all identifiers at time of last
> call; we'll
> * allocate that many unsigned long ints), and go back
> and get 'em.
> */
> if (jpilist[1].bufadr != rlst) Safefree(jpilist[1].bufadr);
> jpilist[1].bufadr = New(1320,mask,rsz,unsigned long int);
> jpilist[1].buflen = rsz * sizeof(unsigned long int);
> _ckvmssts(sys$getjpiw(0,NULL,NULL,&jpilist[1],iosb,NULL,NULL));
> _ckvmssts(iosb[0]);
> }
>
> I made the same mistake when I first looked at this, as did
> the original
> author of the code when he suggested the fix I repeated.
> However, due to
> the dark magic of item lists, the $getjpiw call will fill in
> rsz, supposedly
> with the size in bytes of what it really wants to give you
> (but perhaps
> didn't have room for), and it should fill in rlen with the
> amount of stuff
> it *did* actually give you. This entire structure is passed
> to $getjpiw:
>
> struct itmlst_3 jpilist[4] = { {sizeof iprv,
> JPI$_IMAGPRIV, iprv, &dummy},
> {sizeof rlst,
> JPI$_RIGHTSLIST, rlst, &rlen},
> { sizeof rsz,
> JPI$_RIGHTS_SIZE, &rsz, &dummy},
> { 0,
> 0, 0, 0} };
>
> In Anders's case, it's saying "I want to give you 184 bytes,
> but I'm only
> giving you 40 bytes because that's all I have room for."
> This is bogus
> because the default buffer size is 512. So, the best theory
> I have is that
> $getjpiw is returning a rightslist smaller than the size it
> knows it should
> need, and it may be doing this because there are no system
> identifiers, if
> indeed this is the same problem someone noticed a couple of years ago.
>
> Possibly some other corruption of the rights database could cause the
> problem, and the real solution is to fix the system.
> However, we should
> protect Perl from this if we can come up with a reliable,
> low-cost way of
> doing so. This might be one way to do that, though I can't test it.
> Anders, if you are still wth us, would it be possible to take
> it for a spin?
>
> --- vms/vms.c;-0 Tue Jul 11 15:40:25 2000
> +++ vms/vms.c Mon Jul 24 18:05:15 2000
> @@ -2906,6 +2906,11 @@
> jpilist[1].buflen = rsz * sizeof(unsigned long int);
> _ckvmssts(sys$getjpiw(0,NULL,NULL,&jpilist[1],iosb,NULL,NULL));
> _ckvmssts(iosb[0]);
> + /* If it gave us less than it wanted to despite ample
> buffer space, it's
> + broken. Is your system missing a system identifier? */
> + if (rlen < rsz && rsz <= sizeof(jpilist[1].buflen)) {
> + Perl_croak(aTHX_ "Error getting rights in
> vms_image_init: check your rights database.");
> + }
> }
> mask = jpilist[1].bufadr;
> /* Check attribute flags for each identifier (2nd
> longword); protected
> [end of possible kernel-mode endless loop avoidance patch]
>
> _______________________________________________
> Craig A. Berry
> mailto:[EMAIL PROTECTED]
>