Hi,
I am running a PHP script at the command line and piping the output through less:
./myScript | less
Since less is an interactive program it puts the terminal into 'raw' mode so
that it can read characters one at a time. However, when I do the above I find
that the commands that I type to less are echoed back to me and not acted on
until I type <RETURN>. This is not as it should be.
The sript is not doing anything clever, just generating 100 lines:
for($i = 0; $i < 100; $i++)
echo "i=$i\n";
If I run the script under strace I see:
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig icanon echo ...}) = 0
What is happening is that PHP is putting the terminal into cooked mode.
I can get it to not do this by connecting stdin to /dev/null:
./myScript < /dev/null | less
another way of getting it to work is (and this shows that it really is PHP that
is messing the tty modes):
./myScript < /dev/null | (sleep 10; less)
However: PHP should not set the terminal to cooked mode in the first place.
Is there any way in which I can get PHP to not do this ?
TIA
I am running PHP 5.3.3 on CentOS 6.
I posted this to php-general@lists.php.net a few days ago, but did not get a
sensible reply.
--
Alain Williams
Linux/GNU Consultant - Mail systems, Web sites, Networking, Programmer, IT Lecturer.
+44 (0) 787 668 0256 http://www.phcomp.co.uk/
Parliament Hill Computers Ltd. Registration Information: http://www.phcomp.co.uk/contact.php
#include <std_disclaimer.h
./myScript | less
Since less is an interactive program it puts the terminal into 'raw' mode so
that it can read characters one at a time. However, when I do the above I find
that the commands that I type to less are echoed back to me and not acted on
until I type <RETURN>. This is not as it should be.If I run the script under strace I see:
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig icanon echo ...}) = 0
What is happening is that PHP is putting the terminal into cooked mode.
Are you sure it is PHP that's doing this? There are basically no calls
to ioctl() (or tcsetattr() for that matter) outside of ext/ at all.
- Martin
./myScript | less
Since less is an interactive program it puts the terminal into 'raw' mode so
that it can read characters one at a time. However, when I do the above I find
that the commands that I type to less are echoed back to me and not acted on
until I type <RETURN>. This is not as it should be.If I run the script under strace I see:
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig icanon echo ...}) = 0
What is happening is that PHP is putting the terminal into cooked mode.
Are you sure it is PHP that's doing this? There are basically no calls
to ioctl() (or tcsetattr() for that matter) outside of ext/ at all.
I have done a bit of digging and suspect that this happens as part of readline initialisation.
phpinfo()
reports: --without-readline but then:
Additional Modules
Module Name
readline
sysvsem
sysvshm
/usr/lib64/libedit.so.0
The system calls at about the time that it does the ioctl() on stdin are:
brk(0x2b18000) = 0x2b18000
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
rt_sigprocmask(SIG_BLOCK, [WINCH], [], 8) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
stat("/home/addw/.terminfo", 0x7fff0ec06750) = -1 ENOENT (No such file or directory)
stat("/etc/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
access("/etc/terminfo/x/xterm", R_OK) = -1 ENOENT (No such file or directory)
stat("/usr/share/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
access("/usr/share/terminfo/x/xterm", R_OK) = 0
open("/usr/share/terminfo/x/xterm", O_RDONLY) = 3
read(3, "\32\0010\0&\0\17\0\235\1l\5xterm|xterm terminal"..., 4097) = 3258
close(3) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TIOCGWINSZ, {ws_row=65, ws_col=237, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(0, TIOCGWINSZ, {ws_row=65, ws_col=237, ws_xpixel=0, ws_ypixel=0}) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig icanon echo ...}) = 0
rt_sigprocmask(SIG_BLOCK, [HUP INT QUIT TERM CONT STOP TSTP WINCH], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
open("/home/addw/.editrc", O_RDONLY) = -1 ENOENT (No such file or directory)
--
Alain Williams
Linux/GNU Consultant - Mail systems, Web sites, Networking, Programmer, IT Lecturer.
+44 (0) 787 668 0256 http://www.phcomp.co.uk/
Parliament Hill Computers Ltd. Registration Information: http://www.phcomp.co.uk/contact.php
#include <std_disclaimer.h
I have done a bit of digging and suspect that this happens as part of readline initialisation.
That might very well be it.
--
Regards,
Mike
Le 17/09/2013 02:27, Alain Williams a écrit :
I have done a bit of digging and suspect that this happens as part of readline initialisation.
+1
phpinfo()
reports: --without-readline but then:
Please... don't rely, for distro packaged PHP on configure option listed
in phpinfo report [1].
Additional Modules Module Name readline
readline extension doesn't use readline library (under incompatible
license: GPLv3) but libedit (License: BSD).
Remi.
[1] http://blog.famillecollet.com/post/2010/09/29/phpinfo-BUG-or-PEBKAC
Please... don't rely, for distro packaged PHP on configure option listed
in phpinfo report [1].Additional Modules Module Name readline
readline extension doesn't use readline library (under incompatible
license: GPLv3) but libedit (License: BSD).
Running php and looking at the /proc/../maps file I see that it has mapped /usr/lib64/libedit.so.0.0.27
Looking at the symbol table I see the symbol tcsetattr -- this sets terminal
modes in the way that I was seeing from the system call trace.
What is needed is for this to NOT be called if the standard output is not
connected to a tty.
Should I raise this as a bug ?
Remi.
--
Alain Williams
Linux/GNU Consultant - Mail systems, Web sites, Networking, Programmer, IT Lecturer.
+44 (0) 787 668 0256 http://www.phcomp.co.uk/
Parliament Hill Computers Ltd. Registration Information: http://www.phcomp.co.uk/contact.php
#include <std_disclaimer.h
Le 18/09/2013 16:04, Alain Williams a écrit :
What is needed is for this to NOT be called if the standard output is not
connected to a tty.
From your previous message:
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig icanon echo ...}) = 0
Which is standard input, not standard output
I can get it to not do this by connecting stdin to /dev/null:
./myScript < /dev/null | less
qed
Should I raise this as a bug ?
So, I don't think there is any bug there.
Remi.
I've seen something similar on Debian; it might be a patch that
your distro is shipping on top of PHP.
Edward
Excerpts from Alain Williams's message of Sat Sep 14 04:45:41 -0700 2013:
Hi,
I am running a PHP script at the command line and piping the output through less:
./myScript | less
Since less is an interactive program it puts the terminal into 'raw' mode so
that it can read characters one at a time. However, when I do the above I find
that the commands that I type to less are echoed back to me and not acted on
until I type <RETURN>. This is not as it should be.The sript is not doing anything clever, just generating 100 lines:
for($i = 0; $i < 100; $i++)
echo "i=$i\n";If I run the script under strace I see:
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig icanon echo ...}) = 0
What is happening is that PHP is putting the terminal into cooked mode.
I can get it to not do this by connecting stdin to /dev/null:
./myScript < /dev/null | less
another way of getting it to work is (and this shows that it really is PHP that
is messing the tty modes):./myScript < /dev/null | (sleep 10; less)
However: PHP should not set the terminal to cooked mode in the first place.
Is there any way in which I can get PHP to not do this ?
TIA
I am running PHP 5.3.3 on CentOS 6.
I posted this to php-general@lists.php.net a few days ago, but did not get a
sensible reply.
I've seen something similar on Debian; it might be a patch that
your distro is shipping on top of PHP.
Nope, I reviewed the Debian PHP patches the other day.
--
Regards,
Mike