Prev: FAQ 7.12 How can I tell if a variable is tainted?
Next: will there be a Strawberry Perl 6 / Rakudo Star ?
From: Dr.Ruud on 10 May 2010 15:47 David Resnick wrote: > I've been poking at a script that loses the ability to ready from > <STDIN> after doing a system() call. > > I located this > http://perldoc.perl.org/perlfaq8.html#Why-can%27t-my-script-read-from-STDIN-after-I-gave-it-EOF-%28^D-on-Unix,-^Z-on-MS-DOS%29? > which seemed to be the obvious answer to my questions. > > But after doing this: > STDIN->clearerr(); > > or this: > > seek STDIN, 0, SEEK_SET Here I decided that you need to read `perldoc -f open`. Look for "perlipc". -- Ruud
From: David Resnick on 11 May 2010 08:59 On May 10, 2:45 pm, Ben Morrow <b...(a)morrow.me.uk> wrote: > Quoth David Resnick <lndresn...(a)gmail.com>: > > > > > On May 10, 12:56 pm, Ben Morrow <b...(a)morrow.me.uk> wrote: > > > Quoth David Resnick <lndresn...(a)gmail.com>: > > > > > I've been poking at a script that loses the ability to ready from > > > > <STDIN> after doing a system() call. > > > > Please post your code, and also your OS and version of perl. Something > > > like > > > > perl -E'system "cat"; say scalar <STDIN>;' > > > > works just fine for me here. (The first ^D sends EOF to cat, and any > > > subsequent lines are happily read by perl.) > > > As I mentioned in the follow up, closing stdin on the system command > > fixed it. > > > It does not apply to any command, I discovered that early on. Once I > > saw that the "system" command is what seemed to mess up my STDIN, I > > tried the "date" run via system, didn't cause the issue. > > > The relevant part of the code is here. Note sipp is an open source > > tool to handle SIP traffic. When run normally it does look for input > > in STDIN. > > > getline("hit return when ready to execute test $testName\n"); > > > my $sippCommand = "$vobBase/thparty3/sipp/sipp -sf " .. > > "$sippFile $remoteIpAddress -trace_msg -m 1 -l 1 -key > > testname $testName -key testdir $outputDirRoot/$testName" . > > " > /dev/null 2> /dev/null 0<&-"; > > It's generally safer to redirect stdin from /dev/null rather than > closing it. Closing it means the first file sipp opens will appear on > its fd 0, which may have unfortunate consequences. > > > If I don't do the 0<&- in the system call, all future calls to <STDIN> > > return eof. But that seems to fix my problem, so I'm now merely just > > curious as to why this happens. I'm still mystified as to why, as I > > thought that system would create an independent process that couldn't > > alter its parents file descriptor state in any way. > > It does create a separate process, but the two filehandles are still > somewhat connected. I can't see, off the top of my head, what sipp could > be doing to cause your STDIN to return EOF, but if you're interested you > could run the whole thing under strace to find out what it actually does > to fd 0. > > Ben I was still a bit curious, so I examined the sipp source code for how they mucked with stdin. Here is a minimal perl script and C program that allows reproduction of the problem. temp(1726)$ cat foo.pl #!/usr/bin/perl -w use strict; my $line = <STDIN>; print "got: $line"; if ( ! $line ) { die("STDIN returns undef before system call"); } system("foo"); $line = <STDIN>; if ( ! $line ) { die("STDIN returns undef before system call"); } print "got: $line"; *********** temp(1727)$ cat foo.c #include <unistd.h> #include <fcntl.h> #include <stdio.h> int main(void) { printf("about to fcntl\n"); fcntl(fileno(stdin), F_SETFL, fcntl(fileno(stdin), F_GETFL) | O_NONBLOCK); return 0; } Hmmm. Apparently this fcntl crocks the parent perl scripts STDIN. OK, I have a work around, guess I'm done with this issue. Thanks for your help! -David
From: Uri Guttman on 11 May 2010 14:46 >>>>> "DR" == David Resnick <lndresnick(a)gmail.com> writes: DR> I was still a bit curious, so I examined the sipp source code for how DR> they mucked with stdin. Here is a minimal perl script and C program DR> that allows reproduction of the problem. and it is now obvious what the cause of the problem is. DR> system("foo"); stdin is no in nonblocking mode (what foo does). so since you haven't typed anything quickly, <> will return immediately and be undef. sipp/foo are doing async stdio, likely some form of terminal screen stuff or whatever. clean programs will return stdin to the normal blocking mode when they exit. you can do that in your perl easily with IO::Handle's nonblocking method. something like this should do: use IO::Handle ; STDIN->nonblocking(0) ; DR> *********** DR> printf("about to fcntl\n"); DR> fcntl(fileno(stdin), F_SETFL, fcntl(fileno(stdin), F_GETFL) | DR> O_NONBLOCK); DR> Hmmm. Apparently this fcntl crocks the parent perl scripts STDIN. DR> OK, I have a work around, guess I'm done with this issue. Thanks for DR> your help! if your workaround is anything more complex than mine, switch it. all you need to do is set clear the nonblocking flag after you run sipp. uri -- Uri Guttman ------ uri(a)stemsystems.com -------- http://www.sysarch.com -- ----- Perl Code Review , Architecture, Development, Training, Support ------ --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
From: David Resnick on 11 May 2010 17:07 On May 11, 2:46 pm, "Uri Guttman" <u...(a)StemSystems.com> wrote: > >>>>> "DR" == David Resnick <lndresn...(a)gmail.com> writes: > > DR> I was still a bit curious, so I examined the sipp source code for how > DR> they mucked with stdin. Here is a minimal perl script and C program > DR> that allows reproduction of the problem. > > and it is now obvious what the cause of the problem is. > > DR> system("foo"); > > stdin is no in nonblocking mode (what foo does). so since you haven't > typed anything quickly, <> will return immediately and be > undef. sipp/foo are doing async stdio, likely some form of terminal > screen stuff or whatever. clean programs will return stdin to the normal > blocking mode when they exit. you can do that in your perl easily with > IO::Handle's nonblocking method. something like this should do: > > use IO::Handle ; > > STDIN->nonblocking(0) ; > > DR> *********** > DR> printf("about to fcntl\n"); > DR> fcntl(fileno(stdin), F_SETFL, fcntl(fileno(stdin), F_GETFL) | > DR> O_NONBLOCK); > > DR> Hmmm. Apparently this fcntl crocks the parent perl scripts STDIN. > DR> OK, I have a work around, guess I'm done with this issue. Thanks for > DR> your help! > > if your workaround is anything more complex than mine, switch it. all > you need to do is set clear the nonblocking flag after you run sipp. > ----- Thanks for the comments. My work around is simple, in the system() invocation I redirect stdin to take input from /dev/null (closing stdin in the system call also works). I think (and you suggest above) that it is a bug in sipp -- it should put stdin back to how it found it prior to exiting. I may suggest that to the sipp devs. The part that surprised me and made this a bit painful was that I had no idea the process launched by the system command could muck with the parents i/o. I guess I had an understanding that after system fork and execs the new command the new process was basically independent. Apparently not completely... -David
From: Uri Guttman on 11 May 2010 18:20 >>>>> "DR" == David Resnick <lndresnick(a)gmail.com> writes: DR> My work around is simple, in the system() invocation I redirect stdin DR> to take input from /dev/null (closing stdin in the system call also DR> works). I think (and you suggest above) that it is a bug in sipp -- DR> it should put stdin back to how it found it prior to exiting. I may DR> suggest that to the sipp devs. normally the shell will return the terminal to a sane mode (it didn't in the old days) and the sipp dev team may not have noticed for that reason. DR> The part that surprised me and made this a bit painful was that I DR> had no idea the process launched by the system command could muck DR> with the parents i/o. I guess I had an understanding that after DR> system fork and execs the new command the new process was DR> basically independent. Apparently not completely... forked processes have their own memory and many private things but they can share stdio and usually do. that is how sipp even gets to use stdio from the terminal after you fork it. otherwise it wouldn't be able to get any terminal i/o. this has always been the case for unix forking. the shell opens (or rather init does) the terminal one time and the 3 fds (0,1,2) are share with forked children so they can do stdio and not need to know which terminal to open. the other side of this is when you want a child not to deal with the terminal it will usually close stdio. in your case redirectling stdin from /dev/null did it. uri -- Uri Guttman ------ uri(a)stemsystems.com -------- http://www.sysarch.com -- ----- Perl Code Review , Architecture, Development, Training, Support ------ --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
First
|
Prev
|
Pages: 1 2 Prev: FAQ 7.12 How can I tell if a variable is tainted? Next: will there be a Strawberry Perl 6 / Rakudo Star ? |