This is the mail archive of the mailing list for the Cygwin project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Bug in select/read with serial tty

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)
  if (n == 0) {

  if (FD_ISSET(f, &ibits)) {
    fcc = read(f, fibuf, sizeof(fibuf));
    if (fcc < 0 && errno == EWOULDBLOCK)
      fcc = 0;
    else {
      if (fcc <= 0)
      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
WaitCommEvent() returns immediately with a non-zero result even
though.cbInQue == 0.

  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;
     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


begin 666 bug.c
M(VEN8VQU9&4@/'1E<FUI;RYH/@HC:6YC;'5D92 \97)R;F\N:#X*(VEN8VQU
M9&4@/&9C;G1L+F at ^"B-I;F-L=61E(#QC='EP92YH/@HC:6YC;'5D92 \<W1R
M:6YG+F at ^"B-I;F-L=61E(#QT:6UE+F at ^"@II;G0 at =7-E2VQU9&=E(#T@,#L*
M:6YT('5S94-25%-#5%,@/2 P.PH*(V1E9FEN92!#5$PH>"D at *'@@7B P,3 P
M*0DO*B!!<W-U;65S($%30TE)(&1I86QE8W0 at *B\*"FEN=" @(" @;6%I;BAA
M<F=C+"!A<F=V*0II;G0@(" @(&%R9V,["F-H87(@("HJ87)G=CL*>PIC:&%R
M('1T>7-T<ELU,%T@/2 B+V1E=B]T='ES,2(["FEN="!F.PIS=')U8W0 at =&5R
M;6EO('1I;SL)"2\J('1E<FUI;F%L(&UO9&4 at 8FET<R J+PIS=')U8W0@<W1A
M="!S=#L*:6YT(" @("!C.PIE>'1E<FX at 8VAA<B J;W!T87)G.PD)+RH at 9V5T
M;W!T("HO"F5X=&5R;B!I;G0@;W!T:6YD.PD)"2\J(&=E=&]P=" J+PH*=VAI
M;&4 at *&ES87-C:6DH8R ](&=E=&]P="AA<F=C+"!A<F=V+" B:V at B*2DI('L*
M"7-W:71C:" H8RD@>PH)8V%S92 G:R<Z"0D)"2\J(&]N92!S=&]P(&)I=" J
M+PH)"75S94ML=61G92 ](#$["@D)8G)E86L["@EC87-E("=H)SH)"0D)+RH@
M;VYE('-T;W @8FET("HO"@D)=7-E0U)44T-44R ](#$["@D)8G)E86L["@ED
M969A=6QT dot  at H)(" @('L*"0EP<FEN=&8H(DEN=F%L:60@;W!T:6]N("<M)6,G
M7&XB+"!C*3L*"0EE>&ET*# I.PD)"@D@(" @?0H)(" @(&)R96%K.PH)?0I]
M"0H*:68 at *&%R9V,@/3T@;W!T:6YD("L@,2D@>PH)<W1R8W!Y*'1T>7-T<BP@
M"FEF("AA<F=C("$](&]P=&EN9"D@>PD)+RH at 8VAE8VL@<&%R86UE=&5R(&-O
M=6YT("HO"@EP<FEN=&8H(DEN=F%L:60 at 87)G<SH@)7,@6RUK75LM:%T at ='1Y
M<S]<;B(L(&%R9W9;,%TI.PH)97AI="@P*3L)"0I]"@D*<')I;G1F("@B)3 Q
M,&0 at 57-I;F<@='1Y("5S7&XB+"!C;&]C:R at I+"!T='ES='(I.PD*:68 at *'5S
M94ML=61G92D@<')I;G1F("@B)3 Q,&0 at 57-I;F<@:VQU9&=E7&XB+"!C;&]C
M:R at I*3L)"FEF("AU<V5#4E130U13*2!P<FEN=&8 at *"(E,#$P9"!5<VEN9R!#
M4E130U137&XB+"!C;&]C:R at I*3L)"@II9B H<W1A="AT='ES='(L("9S="D@
M/" P*2!["@EP<FEN=&8 at *")E<G)O<CH@<W1A="!F86EL961<;B(I.PH)97AI
M="@P*3L*?0H*:68 at *"AS="YS=%]M;V1E("8 at 4U])1DU4*2 A/2!37TE&0TA2
M*2!["@EP<FEN=&8 at *")E<G)O<CH@;F]T(&$ at 8VAA<F%C=&5R(&1E=FEC95QN
M(BD["@EE>&ET*# I.PI]"@II9B H*&8@/2!O<&5N*'1T>7-T<BP at 3U]21%=2
M*2D@/" P*2!["@EP<FEN=&8 at *")E<G)O<CH at 8V%N;F]T(&]P96X at ='1Y7&XB
M*3L*"65X:70 at *# I.PI]"@II9B H:6]C=&PH9BP at 5$-'151!+" F=&EO*2 \
M(# I('L*"7!R:6YT9B H(F5R<F]R.B!I;V-T;"A40T=%5$$I(&9A:6QE9%QN
M(BD["@EE>&ET*# I.PI]"@IT:6\N8U]C9FQA9R ]($-3."!\($A54$-,('P@
M0U)%040 at ?"!",S at T,# ["FEF("AU<V5#4E130U13*0H)=&EO+F-?8V9L86<@
M?#T at 0U)44T-44SL*"0D*=&EO+F-?:69L86<@/2!T:6\N8U]L9FQA9R ]('1I
M;RYC7V]F;&%G(#T@,#L*=&EO+F-?;&EN92 ](# ["G1I;RYC7V-C6U9-24Y=
M(#T@,3L*=&EO+F-?8V-;5E1)345=(#T@,#L*=&EO+F-?:7-P965D(#T at =&EO
M+F-?;W-P965D(#T at =&EO+F-?8V9L86<@)B!#0D%51#L*"FEF("AI;V-T;"AF
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 at *'-T<G5C="!T97)M:6\@
M*BD@,"D["B @(" *=&EO+F-?:69L86<@?#T at 25A/3B!\($E83T9&.PD)+RH@
M,BUW87D at 9FQO=R!C;VYT<F]L("HO"G1I;RYC7VQF;&%G('P]($E#04Y/3B!\
M($E324<@?"!%0TA/('P at 14-(3T4 at ?"!%0TA/2SL*=&EO+F-?;V9L86<@?#T@
M3U!/4U0 at ?"!/3$-50SL*=&EO+F-?8V-;5DE.5%)=(#T at 0U1,*"=#)RD["0DO
M*B!D969A=6QT(&EN=&5R<G5P=" J+PIT:6\N8U]C8UM6455)5%T@/2!#5$PH
M)UQ<)RD["0DO*B!D969A=6QT('%U:70 at *B\*=&EO+F-?8V-;5D5/1ET@/2!#
M5$PH)T0G*3L)"2\J(&1E9F%U;'0 at 14]&(&-H87)A8W1E<B J+PIT:6\N8U]C
M8UM614],72 ]($-43"@G32<I.PD)+RH at 9&5A9G5L="!%3TP at 8VAA<F%C=&5R
M(#T at 0U(@*B\*=&EO+F-?8V-;5D5205-%72 ]($-43"@G2"<I.PD)+RH@<V5T
M(&5R87-E(&-H87)A8W1E<B!T;R!"4R J+PIT:6\N8U]C8UM62TE,3%T@/2!#
M5$PH)U4G*3L)"2\J('-E="!K:6QL(&-H87)A8W1E<B J+PH@(" @"0IT:6\N
M8U]I9FQA9R!\/2!)0U).3#L)"0DO*B!M87 @0U(@:6X@:6YP=70 at =&\ at 3DP@
M*B\*=&EO+F-?;V9L86<@?#T at 3TY,0U(["0D)+RH@;6%P($Y,(&EN(&]U='!U
M="!T;R!#4BU.3" J+PH*:68 at *'5S94-25%-#5%,I"@ET:6\N8U]C9FQA9R!\
M/2!#4E130U13.PH*:68 at *&EO8W1L*&8L(%1#4T5402P@)G1I;RD@/" P*7L*
M"7!R:6YT9B H(F5R<F]R.B!I;V-T;"A40U-%5$$I(&9A:6QE9%QN(BD["@EE
M>&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
M=" ](&-L;V-K*"D["@EP<FEN=&8H(B4P,3!D(&-A;&QI;F<@<V5L96-T7&XB
M+"!C;&]C:R at I*3L*"6EF("@H;B ]('-E;&5C="AF*S$L("9I8FET<RP at 3E5,
M3"P@)F5B:71S+" P*2D@/" P*2!["@D):68 at *&5R<FYO(#T]($5)3E12*0H)
M"0EC;VYT:6YU93L*"0EE>&ET*# I.PH)?0H)<V5L96-T7W0@/2!C;&]C:R at I
M.PH):68 at *&X@/3T@,"D@>PH)"2\J('-H;W5L9&XG="!H87!P96XN+BX at *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 at *&EO8W1L*&8L(%1)3T-)3E$L
M("9C8DEN*2 \(# I('L*"0D)<')I;G1F("@B97)R;W(Z(&EO8W1L*%1)3T-)
M(#T](# @)B8 at =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$@<V%Y<R E9"!B>71E<R!R96%D
M>5QN(BP at 8VQO8VLH*2P@8V));BD["@D)"7)E860H9BP at 9FEB=68L(# I.PH)
M(%1)3T-)3E$@<V%Y<R E9"!B>71E<R!R96%D>5QN(BP at 8VQO8VLH*2P@8V))
M<F5A9%]T(#T at 8VQO8VLH*3L*"0EP<FEN=&8H(B4P,3!D(')E860@)60 at 8GET
M97,L(&EN('-E;&5C=" E9"P@:6X@<F5A9" E9%QN(BP at 8VQO8VLH*2P@9F-C
M+"!S96QE8W1?=" M('-T87)T7W0L(')E861?=" M('-E;&5C=%]T*3L*"0D*
M"0EI9B H9F-C(#P@," F)B!E<G)N;R ]/2!%5T]53$1"3$]#2RD*"0D)9F-C
M(#T@,#L*"0EE;'-E('L*"0D):68 at *&9C8R \/2 P*0H)"0D)8G)E86L["@D)
M"7=R:71E*&8L(&9I8G5F+"!F8V,I.PH)"7T*"7T*?0H*"7)E='5R;B Q.PI]

Unsubscribe info:
Bug reporting:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]