in reply to Help running HTTP::Server::Simple server under the debugger?

The problem seems to be that - when run in the debugger - aliasing socket filehandles (e.g. *STDOUT = $sock) does not work at all -- or the debugger is immediately resetting the standard filehandles to their standard filedescriptor numbers (STDIN = 0, STDOUT = 1, ...).

The following minimal program demonstrates this.

#!/usr/bin/perl use Socket; use FileHandle; socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp")) or die "sock +et: $!"; setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or warn "set +sockopt: $!"; bind(SOCK, sockaddr_in(8080, inet_aton("localhost"))) or die "bind: $! +"; listen(SOCK, SOMAXCONN) or die "listen: $!"; while ( accept(my $sock = FileHandle->new(), SOCK) ) { printf STDERR "before aliasing: sock=%d, STDIN=%d, STDOUT=%d\n", fileno($sock), fileno(STDIN), fileno(STDOUT); *STDIN = $sock; *STDOUT = $sock; printf STDERR "after aliasing: sock=%d, STDIN=%d, STDOUT=%d\n", fileno($sock), fileno(STDIN), fileno(STDOUT); $| = 1; print "enter something:\n"; my $r = <STDIN>; print "you typed: $r"; close $sock; }

First without the debugger.   (After having started the command, run telnet localhost 8080 in another terminal, to connect to the socket...)

$ perl ./aliasing1.pl before aliasing: sock=5, STDIN=0, STDOUT=1 after aliasing: sock=5, STDIN=5, STDOUT=5 ^C $

The telnet session looks like this:

$ telnet localhost 8080 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. enter something: foo you typed: foo Connection closed by foreign host.

However, when running the same program in the debugger, STDIN/STDOUT do remain associated with filedescriptors 0/1:

$ perl -d ./aliasing1.pl Loading DB routines from perl5db.pl version 1.28 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(./aliasing1.pl:5): socket(SOCK, PF_INET, SOCK_STREAM, getpro +tobyname("tcp")) or die "socket: $!"; DB<1> c before aliasing: sock=9, STDIN=0, STDOUT=1 after aliasing: sock=9, STDIN=0, STDOUT=1 enter something: foo you typed: foo ^C IO::Handle::DESTROY(/usr/local/perl-5.8.8/lib/5.8.8/i686-linux/IO/Hand +le.pm:328): 328: sub DESTROY {} DB<1> q $

As a result, IO is performed via the terminal (filedescriptors 0 and 1), instead of via the remote telnet session...

To get this working in the debugger, you have to dup the socket to the filedescriptors 0 and 1 -- i.e. either (as suggested by the OP)

POSIX::dup2(fileno($sock), 0) or die "Cannot dup sock to STDIN: $!"; POSIX::dup2(fileno($sock), 1) or die "Cannot dup sock to STDOUT: $!";

or

open STDIN, "<&", $sock or die "Cannot dup sock to STDIN: $!"; open STDOUT, ">&", $sock or die "Cannot dup sock to STDOUT: $!";

Interestingly though, this seems to apply to sockets only. Aliasing does work just fine with regular-file filehandles, even when using the debugger:

#!/usr/bin/perl my $file = "foo.out"; open my $fh, ">", $file or die "cannot open $file: $!"; printf STDERR "fds before aliasing: fh=%d, STDOUT=%d\n", fileno($fh), fileno(STDOUT); *STDOUT = $fh; printf STDERR "fds after aliasing: fh=%d, STDOUT=%d\n", fileno($fh), fileno(STDOUT); print "foo\n";

Without the debugger:

$ perl ./aliasing2.pl fds before aliasing: fh=3, STDOUT=1 fds after aliasing: fh=3, STDOUT=3

With the debugger:

$ perl -d ./aliasing2.pl Loading DB routines from perl5db.pl version 1.28 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(./aliasing2.pl:3): my $file = "foo.out"; DB<1> c fds before aliasing: fh=8, STDOUT=1 fds after aliasing: fh=8, STDOUT=8 Debugged program terminated. Use q to quit or R to restart, use o inhibit_exit to avoid stopping after program termination, h q, h R or h o to get additional info. DB<1> q

(Note that in both cases, fh and STDOUT have the same filedescriptor number after aliasing. And, as expected, the string "foo" always ends up in the file.)

If anyone can shed some light on why the debugger is treating socket filehandles differently, please do so.

P.S.   sorry for the length :)

Replies are listed 'Best First'.
Re^2: Help running HTTP::Server::Simple server under the debugger?
by shoez (Sexton) on Feb 27, 2007 at 15:55 UTC
    nothing to add to the discussion other than - wonderful work, a very simple, insightful little piece. Thank you.