On Mon, 7 Oct 2002 kuznet@ms2.inr.ac.ru wrote: > Hello! > > > If you log-in over the network, so that a socket is being used, > > I do not understand how to use it in a way that a socket happened > to be stdin. Please, explain. > > Alexey Well stdin actually comes from a virtual terminal, a 'pty', obtained with openpty() from the next available /dev/pty, which gets its data (and SIGIO information) from the connected socket. I modified the prog to show what bits actually being set (none). This should clearly show that something is broken because we can get served a SIGIO signal with no information about the nature of the signal. Also, this signal happens many thousands of times per second. I had over 20,000 lines to delete in only about 2 seconds of operation. I first noted a bad I/O problem with 2.4.19. The network data-transfer rate through a virtual terminal was down from about 2 megabytes per second to about 1.5 kilobytes per second. This was on an embedded system. I traced this down to the overhead necessary to service all the SIGIO signals. I then wrote a program to show the problem. Unfortunately, most all I get is retorts like "Your program is broken...". The program is, clearly, not written to do anything except demonstrate the problem. /* * Modified to show /count the poll bits */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> #include <termios.h> #include <fcntl.h> #include <sys/wait.h> #include <sys/poll.h> #include <errno.h> #include <sys/resource.h> #define ERRORS(s) { \ fprintf(stderr, "Error from line %d, file %s, call %s, (%s)\n", \ __LINE__,__FILE__,(s), strerror(errno)); \ } #define FAIL -1 int enab = 0; int alive = 0; static void set_sig(int sig, sig_t funct, int flags); static void set_sig(int sig, sig_t funct, int flags) { struct sigaction sa; if(sigaction(sig, NULL, &sa) == FAIL) ERRORS("sigaction"); sa.sa_flags = flags; sa.sa_handler = funct; if(sigaction(sig, &sa, NULL) == FAIL) ERRORS("sigaction"); return; } unsigned long polout = 0; unsigned long polerr = 0; static void iotrap(int unused) { struct pollfd pf; pf.fd = STDIN_FILENO; pf.events = POLLIN; pf.revents = 0; (void)poll(&pf, 1, 0); if(pf.revents & POLLIN) enab = 0; if(pf.revents & POLLOUT) polout++; if(pf.revents & POLLERR) polerr++; fprintf(stderr, "POLLOUT = %lu POLLERR = %lu (0x%08lx)\n", polout, polerr, pf.revents); } static void reaper(int unused) { alive = 0; while(wait3(&unused, WNOHANG, NULL) > 0) ; } int main(int args, char *argv[]); int main(int args, char *argv[]) { int flags; size_t i; pid_t pid; struct termios term, save; set_sig(SIGCHLD, reaper, SA_INTERRUPT|SA_RESTART); set_sig(SIGIO, iotrap, SA_INTERRUPT|SA_RESTART); alive = 1; switch((pid = fork())) { case 0: /* Child */ (void)sleep(1); for(i=0; i < 0x10; i++) { fprintf(stderr, "."); (void)sleep(1); } exit(EXIT_SUCCESS); default: break; } /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ /* * Save terminal characteristics and then set the terminal for raw * input generating a signal upon any received character. */ if(tcgetattr(STDIN_FILENO, &term) == FAIL) ERRORS("tcgetattr"); save = term; term.c_lflag = ISIG; term.c_iflag = 0; if(tcsetattr(STDIN_FILENO, TCSANOW, &term) == FAIL) ERRORS("tcsetattr"); if((flags = fcntl(STDIN_FILENO, F_GETFL)) == FAIL) ERRORS("fcntl"); flags |= (FNDELAY|FASYNC); if(fcntl(STDIN_FILENO, F_SETFL, flags) == FAIL) ERRORS("fcntl"); if(fcntl(STDIN_FILENO, F_SETOWN, getpid()) == FAIL) ERRORS("fcntl"); /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ fprintf(stderr, "Waiting for input......."); enab = 1; while(enab) { pause(); fprintf(stderr, "Got out of pause\n"); } if(alive) kill(pid, SIGINT); fprintf(stderr, "Exit okay, cleaning up...\n"); /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ /* * Restore the terminal characteristics before we exit. Note, the * terminal is shared. We can't just exit! */ flags &= ~(FNDELAY|FASYNC); if(fcntl(STDIN_FILENO, F_SETFL, flags) == FAIL) ERRORS("fcntl"); if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &save) == FAIL) ERRORS("tcsetattr"); set_sig(SIGIO, SIG_DFL, SA_INTERRUPT); fprintf(stderr, "Done!\n"); return 0; } If you execute this, logged into a terminal, you get: Waiting for input..........POLLOUT = 0 POLLERR = 0 (0x00000001) Got out of pause Exit okay, cleaning up... Done! If you do `telnet hostname` and execute it, logged in over the network, you get (clearly showing that something is wrong): Note that we got a signal (zillions of times), but no signal bits are set. Waiting for input.......POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) [over 20,000 lines deleted...] POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) POLLOUT = 0 POLLERR = 0 (0x00000000) Cheers, Dick Johnson Penguin : Linux version 2.4.19 on an i686 machine (797.90 BogoMips). The US military has given us many words, FUBAR, SNAFU, now ENRON. Yes, top management were graduates of West Point and Annapolis. - : send the line "unsubscribe linux-net" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html