Steve in Sunnyvale has asked for the wisdom of the Perl Monks concerning the following question:

I'm using the X11::Protocol package to grab an image from the display, which I then shrink into a thumbnail using ImageMagick. The problem is that in certain cases, usually involving the X11 session shutting down while my script is running, my script seems to go into an infinite loop, using 100% CPU.

I believe I have traced this down to a bug in the X11::Protocol::Socket module, but before I report the bug, I want to run it by you experts.

In X11/Protocol/Connection/Socket.pm, I found this code:

sub get { my($self) = shift; my($len) = @_; my($x, $n, $o) = ("", 0, 0); my($sock) = $$self; until ($o == $len) { $n = $sock->sysread($x, $len - $o, $o); croak $! unless defined $n; $o += $n; } return $x; }

Clearly the purpose of this routine is to read a complete X11 response, which includes a header with the size of the rest of the response. In my case I'm calling the X11 function GetImage on the entire display, so the response is rather large. (It is not compressed.)

I believe the issue is that when the X11 server (the display) exits, the sysread() that my script calls will not return an error, but will instead return a 0, which means EOF. This will cause the "until" loop to never end, assuming sysread will continue to return 0 every time it is called after returning 0 once.

If this is what is happening, it would seem that fix would be to add this line after the "croak" line:

croak "end of file" unless $n;

Does that sound reasonable?

By the way, this file is on CPAN.

Update: I found that someone else reported this bug 8 years ago!

Replies are listed 'Best First'.
Re: Bug in X11::Protocol::Socket?
by BrowserUk (Patriarch) on Jun 14, 2016 at 23:50 UTC
    croak "end of file" unless $n;Does that sound reasonable?

    Reasonable, if a little unfriendly.

    I wonder whether you might change it so that that at end of file, it returns whatever it got:

    sub get { my($self) = shift; my($len) = @_; my($x, $n, $o) = ("", 0, 0); my($sock) = $$self; do { $n = $sock->sysread($x, $len - $o, $o); croak $! unless defined $n; $o += $n; } until $o == $len or $n == 0; return $x; }

    But maybe there is no circumstance in which getting less than is expected (how does it know how much to expect?) is a recoverable error?


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice. Not understood.