Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com X-Injected-Via-Gmane: http://gmane.org/ To: cygwin AT cygwin DOT com From: "BB" Subject: Bug in select/read with serial tty Date: Fri, 28 Mar 2003 18:44:08 -0600 Lines: 238 Message-ID: Reply-To: "BB" X-Complaints-To: usenet AT main DOT gmane DOT org X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2800.1106 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 In a nutshell - select does not alway block correctly when no data is available on a serial tty. This is not an agetty problem, but it experienced while using agetty. While trying to use agetty on Win9x platforms I ran into a problem. For some reason, when I connected to the machine running agetty either with a direct nul modem cable or a modem, I was forced to occasionally type 1 more character to get things to happen. For instance, agetty would read my login id and exec login. login would prompt for my password. If I typed "passwd\r". Nothing would happen. The reason is that the '\r' is the first of a pair of characters. If I then typed any character, the password would be processed and I would be logged in. Once I was logged in, if I typed "ls -l\r" I would see the echoed characaters after only every second character. I would then immediately see the output of the command because the \r was the second of a pair. The problem is not specific to agetty. I think it is either a problem with select or read. Attached is a program that illustrates the problem. Here is a portion of the code edited for this message that will experience the problem. Once connected, I simply send one character at a time. The initial call to select blocks until I send a character. FD_ISSET() returns true so the character is read and echoed. (in agetty, it is not echoed, it is sent to the pty) . After looping, select is called again. The expected behavior, as occurs with WinXP, would be for the select to block until I send more data. It does not. FD_ISSET() returns true and the read blocks until I press another character. This blocking read is what forces me to type another character when using agetty. By sending at least one more character, the read returns and the echoed data from the pty is read. /* ... /dev/ttys0 was open for rw as f */ for (;;) { fd_set ibits, obits, ebits; FD_ZERO(&ebits); FD_ZERO(&ibits); FD_ZERO(&obits); FD_SET(f, &ibits); /* f is the tty opened for rw */ if ((n = select(f+1, &ibits, NULL, &ebits, 0)) < 0) { if (errno == EINTR) continue; exit(0); } if (n == 0) { sleep(5); continue; } if (FD_ISSET(f, &ibits)) { fcc = read(f, fibuf, sizeof(fibuf)); if (fcc < 0 && errno == EWOULDBLOCK) fcc = 0; else { if (fcc <= 0) break; write(f, fibuf, fcc); } } } Below is sample output from the attached program *** annotated *** a bit... *** Runing on Win98, problem occurs *** $ ./bug ttys1 0014542875 Using tty /dev/ttys1 *** the first select blocks *** 0014544243 calling select 0014552829 calling read, TIOCINQ says 1 bytes ready 0014552839 read 1 bytes, in select 8586, in read 10 *** select does not block as it should *** 0014552841 calling select *** 0 bytes ready according to ioctl(f, TIOCINQ, &cbIn) 0014552846 calling read, TIOCINQ says 0 bytes ready *** the read blocks until 1 byte was sent *** 0014564430 read 1 bytes, in select 5, in read 11584 *** now select blocks *** 0014564443 calling select 0014570269 calling read, TIOCINQ says 1 bytes ready 0014570279 read 1 bytes, in select 5826, in read 10 *** again, select does not block *** 0014570281 calling select 0014570287 calling read, TIOCINQ says 0 bytes ready *** Runing on Win98 with a kludge to read 0 bytes *** 0014611300 Using tty /dev/ttys1 0014611311 Using kludge *** the first select blocks *** 0014612719 calling select 0014616558 calling read, TIOCINQ says 1 bytes ready 0014616564 read 1 bytes, in select 3839, in read 6 *** select does not block as it should *** 0014616566 calling select *** the kluge read 0 bytes which causes the next select to block *** 0014616571 calling read of 0 bytes, TIOCINQ says 0 bytes ready *** this select blocks *** 0014616576 calling select 0014621438 calling read, TIOCINQ says 1 bytes ready 0014621443 read 1 bytes, in select 4862, in read 5 *** again, select does not block as it should *** 0014621446 calling select 0014621451 calling read of 0 bytes, TIOCINQ says 0 bytes ready 0014621456 calling select 0014625383 calling read, TIOCINQ says 1 bytes ready 0014625388 read 1 bytes, in select 3927, in read 5 0014625391 calling select 0014625396 calling read of 0 bytes, TIOCINQ says 0 bytes ready 0014625401 calling select The select does not block every second time because in .../winsup/cygwin/select.cc, WaitCommEvent() returns immediately with a non-zero result even though.cbInQue == 0. peek_serial() { ... if (!fh->overlapped_armed) { COMSTAT st; ResetEvent (fh->io_status.hEvent); if (!ClearCommError (h, &fh->ev, &st)) { debug_printf ("ClearCommError"); goto err; } else if (st.cbInQue){ return s->read_ready = true; } else if (WaitCommEvent (h, &fh->ev, &fh->io_status)) { /*<<<=====*/ return s->read_ready = true; } else if (GetLastError () == ERROR_IO_PENDING) { fh->overlapped_armed = 1; } else { debug_printf ("WaitCommEvent"); goto err; } ... } I could look into this more, but I haven't had much luck debugging the Cygwin dll code. I can't seem to build the system so I can trace into the read. BB. begin 666 bug.c M(VEN8VQU9&4@/'1E"D@*'@@7B P,3 P M*0DO*B!!PIC:&%R M('1T>7-TPH)8V%S92 G:R&ET*# I.PD)"@D@(" @?0H)(" @(&)R96%K.PH)?0I] M"0H*:68@*&%R9V,@/3T@;W!T:6YD("L@,2D@>PH)7-TPD)+RH AT 8VAE8VL@<&%R86UE=&5R(&-O M=6YT("HO"@EP&ET*# I.PI]"@II9B H*&8@/2!O<&5N*'1T>7-T&ET*# I.PI]"@IT:6\N8U]C9FQA9R ]($-3."!\($A54$-,('P@ M0U)%040@?"!",S AT T,# ["FEF("AUPH)<')I;G1F("@B97)R;W(Z(&EO8W1L M*%1#4T5402D AT 9F%I;&5D7&XB*3L*"65X:70H,"D["GT*"BAV;VED*2!S;&5E M<"@Q*3L**'9O:60I(&EO8W1L*&8L(%1#1DQ32"P@*'-T&ET*# I.PI]"@IC;&]C:U]T('-T87)T7W0L('-E;&5C=%]T+"!R96%D7W0[ M"F-H87(@9FEB=69;,3 R-"LQ72P AT 9F]B=69;,3 R-"LQ73L*:6YT(&XL(&9C M8RP AT 8V));CL*"0IF;W(@*#L[*2!["@EF9%]S970@:6)I=',L(&]B:71S+"!E M8FET&ET*# I.PH)?0H)PH)"2\J('-H;W5L9&XG="!H87!P96XN+BX@*B\* M"0ES;&5E<"@U*3L*"0EC;VYT:6YU93L*"7T*"6EF("A&1%])4U-%5"AF+" F M:6)I=',I*2!["@D)8V));B ](# ["@D):68@*&EO8W1L*&8L(%1)3T-)3E$L M("9C8DEN*2 \(# I('L*"0D)<')I;G1F("@B97)R;W(Z(&EO8W1L*%1)3T-) M3E$I(&9A:6QE9%QN(BD["@D)"65X:70H,"D["@D)?0H)"0H)"6EF("AC8DEN M(#T](# @)B8@=7-E2VQU9&=E*2!["@D)"7!R:6YT9B AT B)3 Q,&0 AT 8V%L;&EN M9R!R96%D(&]F(# @8GET97,L(%1)3T-)3E$@71E5QN(BP AT 8VQO8VLH*2P AT 8V));BD["@D)"7)E860H9BP AT 9FEB=68L(# I.PH) M"0EC;VYT:6YU93L*"0E]"@D)<')I;G1F*"(E,#$P9"!C86QL:6YG(')E860L M(%1)3T-)3E$@71E5QN(BP AT 8VQO8VLH*2P AT 8V)) M;BD["@D)9F-C(#T@