linux454 has asked for the wisdom of the Perl Monks concerning the following question:

A colleague and myself noticed a very peculiar behaviour of $! and $@. We were wondering if someone could shed some light on this strange behavior. Basically, we have an XML document that we are transmitting from a server to a client. Before we send this document we transmit the length of document in four bytes that are arranged in network byte order. The recieving side reads these bytes off and and determines the content length, and then reads off that many bytes. As the server code is currently implemented, it calls a function to open a unix domain socket, if this fails the function returns $@. The return values of the connector function are captured in a couple of variables and eventually end up being concatenated into a return message. The length of this message is then calculated. And the length as outlined above and the message are transmitted back to the client. The problem is that we are getting descrepancies in length. The server says that it's string is 462, but when the client reads off the length it sees 451. One might think, aha there is a bug in the client code, alas one would be wrong. When $@ is taken out of the picture, and everything is the same, the code works as expected. Stabbing in the dark we tried some other permutations. We tried referencing $@ directly this caused no change. We attempted to assign the contents of $@ to another variable, to no avail. We've also tried explicitly stringifying $@, and this didn't work. We also compared what length() returned when given $@ and a string literal which contained the same string as $@. Then we tried returning $!, the server showed the length as 413, the client saw the length as 450, but only read 414 which was the whole message. The next scenario involved referencing $! directly. This last one worked as expected. This has completely baffled us. We've checked to make sure $@ wasn't an object or anything funny. This is completely mind boggling. Anyone have something similiar happen, are we missing something? Update:
Some more detail:
The server will generate

Replies are listed 'Best First'.
Re: $! and $@ peculiarities
by matija (Priest) on May 07, 2004 at 22:50 UTC
    Right off the bat, I see two possibilities:
    • More probable:The server or the client is on a windows system, and you're not setting binmode as you write it out (or read it in). Therefore, you're getting newlines translated from one form into another.
    • Less probable:What do the local settings on the two machines say? Do they differ significantly? Does your XML file contain binary data? Could Perl be doing some funky character set translation on it due to locale misunderstanding?
      Sorry, I forgot those little details. Both platforms are Linux, with a a 2.4.22 or later kernels, (though a client run on the same box as the server has the same issues). We are both running perl-5.8.2. The server and client are connecting via SSL, openssl-0.9.7d. I tried the binmode suggestion but calling binmod($sock) causes an error stating there is no BINMODE handler in IO::Socket::SSL. Though through further testing, we have discovered that this issue isn't directly tied to $! and $@, though at first it was only manifesting itself when they were used. Now this odd behaviour seems to happen anytime a dynamic string is used. String literals seem to function fine.
        Has any of the data you're transmitting been (possibly inadvertently) converted into UTF8? In this case, the length of the string does not match the number of bytes it contains, eg
        my $s = "ab"; $s .= "\x{100}"; open F, ">/tmp/x"; print F $s; close F; printf "length = %d, size = %d\n", length $s, -s '/tmp/x';
        gives
        Wide character in print at /tmp/p line 7. length = 3, size = 4
Re: $! and $@ peculiarities
by dave_the_m (Monsignor) on May 07, 2004 at 22:37 UTC
    This description is almost completely incomprehensible. Why not reduce the server side to a simple standalone piece of test code that just writes the data to a file rather than a client; then if the problem persists, you can post the code here and we can examine it.

    $@ is just a global variable who's value is set after an eval is executed, and $! is a funny dual-valued variable (both integer and string) who's value is meaningful at the point of return from a Perl system function which has indicated failure, and who's documentation implies that it sets $! on failure. At any other points during code execution, its value is meaningless.

Re: $! and $@ peculiarities
by raptnor2 (Beadle) on May 08, 2004 at 11:34 UTC
    I won't comment on the difference between $! and $@, because others have done a better job than I could do. I would like to recommend that you take a look at SOAP::Lite. It can be used to create both clients and servers (as standalone or as CGI). It moves you higher up the protocol stack, but it should eliminate your problems.

    You can pass any native Perl value through. It handles converting it to and from SOAP formats. You can pass XML through as a string or if your XML is based on Perl arrays or hashes you can pass those right through instead. In one of my programs it removed a hundred or more lines of Perl code on the client and replace it with about 10 lines (much easier to maintain..:). It also has a compression option which can save bandwidth.

    The SOAP::Lite Cookbook can be found here if you are interested.

    Cheers,

    John