[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Help-bash] EOF ('\004') was lost if it's sent to bash too quickly
From: |
Clark Wang |
Subject: |
[Help-bash] EOF ('\004') was lost if it's sent to bash too quickly |
Date: |
Wed, 2 Nov 2016 00:02:13 +0800 |
Hi,
I'm learning about the mysterious pty things and wrote a small program (a
lot of code from the APUE book) named pty.c (attached). It works like this:
- The main() process copies data from stdin to ptm (pty master) and from
ptm to stdout. When stdin is EOF then write '\004' to ptm.
- The child process exec() the specified command on pts (pty slave).
The big loop function:
194 void
195 big_loop(int fd_ptym)
196 {
197 char buf[4096];
198 int nread;
199 int r, status;
200 struct timeval timeout;
201 fd_set readfds;
202 bool stdin_eof = false;
203
204 while (true) {
205 FD_ZERO(&readfds);
206 if (!stdin_eof) {
207 FD_SET(STDIN_FILENO, &readfds);
208 }
209 FD_SET(fd_ptym, &readfds);
210
211 timeout.tv_sec = 0;
212 timeout.tv_usec = 100 * 1000;
213
214 r = select(fd_ptym + 1, &readfds, NULL, NULL, &timeout);
215 if (r == 0) {
216 continue;
217 } else if (r < 0) {
218 if (errno == EINTR) {
219 continue;
220 } else {
221 fatal_sys("select error");
222 }
223 }
224
225 if (!stdin_eof && FD_ISSET(STDIN_FILENO, &readfds) ) {
226 nread = read(STDIN_FILENO, buf, sizeof(buf) );
227 if (nread <= 0) { /* EOF from stdin */
228 stdin_eof = true;
229 write(fd_ptym, "\004", 1); /* send <CTRL-D> */
230 } else {
231 write(fd_ptym, buf, nread);
232 }
233 }
234 if (FD_ISSET(fd_ptym, &readfds) ) {
235 nread = read(fd_ptym, buf, sizeof(buf) );
236 if (nread <= 0) { /* child exited */
237 break;
238 }
239 write(STDOUT_FILENO, buf, nread);
240 }
241 }
242
243 wait(&status);
244 if (WIFEXITED(status) ) {
245 exit(WEXITSTATUS(status) );
246 } else if (WIFSIGNALED(status) ) {
247 exit(status + 128);
248 } else {
249 exit(1);
250 }
251 }
The problem is that on Linux (Debian 8.5, x86_64) the following usage would
not exit:
# echo hello | ./pty bash --noprofile --norc
hello
bash-4.3# hello
bash: hello: command not found
bash-4.3# <-- It blocks here.
I started gdb on the bash process and the backtrace is like this:
(gdb) bt
#0 0x00007f21fd548ba0 in __read_nocancel () at
../sysdeps/unix/syscall-template.S:81
#1 0x00000000004acbd7 in rl_getc ()
#2 0x00000000004ad4bd in rl_read_key ()
#3 0x0000000000497b50 in readline_internal_char ()
#4 0x00000000004982a5 in readline ()
#5 0x000000000042178e in ?? ()
#6 0x0000000000423abb in ?? ()
#7 0x0000000000426b7a in ?? ()
#8 0x000000000042a2e4 in yyparse ()
#9 0x00000000004210ab in parse_command ()
#10 0x0000000000421178 in read_command ()
#11 0x0000000000421359 in reader_loop ()
#12 0x000000000041fca5 in main ()
It looks to me that bash did not get the EOF (line #229). But the same code
works fine on Mac (10.11.6, EI Capitan) and on Linux it also works fine
with the cat command:
# echo hello | ./pty cat
hello
hello
#
And if I add a sleep(1) before line #229 it would also work fine with bash
on Linux.
Anyone can help what's the problem? (I'm not sure if writing '\004' to ptm
is the correct way to send EOF to the process on pts.)
Thanks.
-clark
pty.c
Description: Text Data
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Help-bash] EOF ('\004') was lost if it's sent to bash too quickly,
Clark Wang <=