Hi,

As it comes from the manual the 'notty' option will enable pppd to read
and write from stdin/stdout. In order to do it, pppd allocates a
master-slave terminal pair, forks and starts a new 'charshunting'
process, which proxies data between pseudo terminal and stdin/stdout.

At high transfer rates the pppd-2.3.11 dies with "Error writing standard
output" error.

After looking thru the pppd/main.c code (charshunt() function) I figured
that there is a small problem (or call it a bug, if you want).

The following block is part of the proxying loop.

   2096         if (select(nfds, &ready, &writey, NULL, NULL) < 0) {
   2097             if (errno != EINTR)
   2098                 fatal("select");
   2099             continue;
   2100         }
   2101         if (FD_ISSET(ifd, &ready)) {
   2102             ibufp = inpacket_buf;
   2103             nibuf = read(ifd, ibufp, sizeof(inpacket_buf));
   2104             if (nibuf < 0 && errno == EIO)
   2105                 nibuf = 0;
   2106             if (nibuf < 0) {
   2107                 if (!(errno == EINTR || errno == EAGAIN)) {
   2108                     error("Error reading standard input: %m");
   2109                     break;
   2110                 }
   2111                 nibuf = 0;
   2112             } else if (nibuf == 0) {
   2113                 /* end of file from stdin */
   2114                 stdin_readable = 0;
   2115                 /* do a 0-length write, hopefully this will
generate
   2116                    an EOF (hangup) on the slave side. */
   2117                 write(pty_master, inpacket_buf, 0);
   2118                 if (recordf)
   2119                     if (!record_write(recordf, 4, NULL, 0,
&lasttime))
   2120                         recordf = NULL;
   2121             } else {
***2122                 FD_SET(pty_master, &writey);
   2123                 if (recordf)
   2124                     if (!record_write(recordf, 2, ibufp, nibuf,
&lasttime))
   2125                         recordf = NULL;
   2126             }
   2127         }

Note that when this code successfully reads some data from stdin, it
sets a flag in writey, which will fool the following code, and make it
believe that the pty_master is ready for writing:

   2169         if (FD_ISSET(pty_master, &writey)) {
   2170             n = write(pty_master, ibufp, nibuf);
   2171             if (n < 0) {
   2172                 if (errno != EIO) {
   2173                     error("Error writing pseudo-tty master:
%m");
   2174                     break;
   2175                 }
   2176                 stdin_readable = 0;
   2177                 nibuf = 0;
   2178             } else {
   2179                 ibufp += n;
   2180                 nibuf -= n;
   2181             }
   2182         }

The write() function in the above block will return EAGAIN, which will
make the charshunting process exit. Note that the error is returned
because we're attempting to write in pty_master, which is not ready for
writing. The attempt is done because we modified the 'writey' flags in
the first block.

I have no idea why it's necessary to modify flags in the first block, so
I patched this code on my system by just ignoring EAGAIN in the second
block.

- Andrei.

-
To unsubscribe from this list: send the line "unsubscribe linux-ppp" in
the body of a message to [EMAIL PROTECTED]

Reply via email to