Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

Is this a bug in perl or a bug in me?

by Wheely (Acolyte)
on Sep 05, 2011 at 17:34 UTC ( #924278=perlquestion: print w/replies, xml ) Need Help??
Wheely has asked for the wisdom of the Perl Monks concerning the following question:

Hi all!

This problem had me foxed for a while. Basically I am forking a process. One process increments a number and writes it to shared memory every 60 seconds. The child, every 10 seconds, increments another number, reads the shared memory and subtracts the number it finds there. It then prints the result.

If you run this badly written code you will see that 3-1 really does equal 2 in this wonderful perl world. However, 7-2 equals 6!! 13-3 equals 12!!

What seems to be happening is that when the script reads shared memory into the variable $message, it will display it correctly when the contents of shared memory change BUT when you do arithmetic on $message it uses the first value of $message it saw, even after it changes. The solution is to "undef" $message before you read shared memory but it seems a bit odd to me.

<Am i missing some clever thing I really ought to know about (apart from wasting 99 bytes of RAM). Iīve tried this with version 5.8.4 on Solaris and 5.10.0 on OSX

Update: In case anybody is interested, here is the bug report and some responses. There is even a patch :)

Bug Report

#!/usr/bin/perl use IPC::SysV qw(IPC_STAT IPC_PRIVATE IPC_CREAT IPC_EXCL S_IRUSR S_IWU +SR IPC_RMID); $key=shmget(IPC_PRIVATE,100,IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); my $ret=fork(); if($ret>0){ my $int=0; while(1){ ++$int; shmwrite($key,$int,0,99); sleep 60; } } else { my $t=0; while(1){ shmread($key,$message,0,99); ++$t; $result=$t-$message; print "$t - $message is $result\n"; sleep 10; } }

Replies are listed 'Best First'.
Re: Is this a bug in perl or a bug in me?
by moritz (Cardinal) on Sep 05, 2011 at 19:02 UTC

    I don't understand why your code displays the strange results it does. Here are some observations.

    If I change the last loop to read:

    while(1){ shmread($key,$message,0,99); ++$t; my $t_copy = $t; my $message_copy = $message; print "$t_copy - $message_copy is ", $t_copy - $message_copy, +"\n"; sleep 1; }

    it all works out.

    Adding use Devel::Peek and Dump [$t, $message, $result]; to the original loop shows some other interesting results:

    SV = IV(0x1a65bf8) at 0x1a65c08 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x1a65cb0 SV = PVAV(0x1a54f50) at 0x1a65cb0 REFCNT = 1 FLAGS = () ARRAY = 0x19b75a0 FILL = 2 MAX = 2 ARYLEN = 0x0 FLAGS = (REAL) Elt No. 0 SV = PVNV(0x1a10e10) at 0x1a65d58 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 8 NV = 0 PV = 0 Elt No. 1 SV = PVNV(0x1a5eda0) at 0x19a6a60 REFCNT = 1 FLAGS = (POK,pIOK,pNOK,pPOK) IV = 1 NV = 1 PV = 0x1a2c2b0 "2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +0\0\0\0\0\0"\0 CUR = 99 LEN = 104 Elt No. 2 SV = PVNV(0x1a5edc0) at 0x1a65770 REFCNT = 1 FLAGS = (NOK,POK,pNOK,pPOK) IV = 0 NV = 6 PV = 0x1a37f80 "6"\0 CUR = 1 LEN = 16 8 - 2 is 7

    So, lots of trailing \0's in $message. Not sure how that leads to the disconnect between IV/NV and PV though.

    Update: removing the \0's seems to fix it too:

    $message =~ s/\0+//g;

      Looking at memread in, my guess is that the IV field of the variable remains untouched when reading/writing the string portion of the shared memory:

      ... SvPV_force_nolen(sv); dst = SvGROW(sv, (STRLEN) size + 1); Copy(caddr + pos, dst, size, char); SvCUR_set(sv, size); ...

      (assuming that none of the macros actually reset the IV slot). I think this could be construed as a bug.

        This is interesting stuff but I have to admit my knowledge of the perl source extends to more /0īs than shmwrite is padding my $message with :). I had intended to try and copy the variables while I was thinking about this on the train home but then forgot about it :)

        I very much appreciate your input on this though. Having not been using perl or unix for a while I was a bit apprehensive about submitting a bug report on this but I think now, I will.

        Thanks again

        Not touching the IV slot should be fine (and the right thing to do). But it should turn off the pOK and pIOK flags. I'm not familiar enough with the SV* macros called in memread to know whether it does or not.
Re: Is this a bug in perl or a bug in me?
by zentara (Archbishop) on Sep 06, 2011 at 11:26 UTC
      Interesting :) The shared memory operation works fine here though, itīs what pearl seems to be doing with the buffer that is a touch exciting :)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://924278]
Approved by Corion
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (7)
As of 2018-01-19 06:46 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (216 votes). Check out past polls.