bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: read command sometimes misses newline on timeout


From: Martin D Kealey
Subject: Re: read command sometimes misses newline on timeout
Date: Tue, 8 Oct 2024 14:23:02 +1000

OK, running a similar test with instrumentation gets:

$ time (
  trap ' echo BANG ' SIGALRM ;
  while :; do printf TEST; sleep .00$((1+RANDOM%2)); echo; done |
  for ((r=100000 ;r>0; --r)) do line= ; read -t .002 line; rc=$?; [[ $line
= TEST ]] ; echo "STATUS $rc $? $line" ; done
 ) |&
  sort | uniq -c

      1 +# Hit read timeout SIGALRM, run from line 699 in ./read.def #+
STATUS 142 1 TES
      1 +# Hit read timeout SIGALRM, run from line 72 in zread.c #+
STATUS 142 1
      2 +# Hit read timeout SIGALRM, run from line 865 in ./read.def #+
STATUS 142 1 T
      1 +# Hit read timeout SIGALRM, run from line 865 in ./read.def #+
STATUS 142 1 TES
     16 +# Hit read timeout SIGALRM, run from line 913 in ./read.def #+
STATUS 142 0 TEST
   1721 +# Hit read timeout SIGALRM, run from line 913 in ./read.def #+
STATUS 142 1
      3 STATUS 0 0 TEST
  32649 STATUS 0 1
  34367 STATUS 142 0 TEST
  31235 STATUS 142 1
      2 STATUS 142 1 EST
      2 STATUS 142 1 T

real    3m21.411s
user    1m14.054s
sys     1m46.493s

That's to say, that out of 100000 reads:

   - 0.003% had both `read` returning 0 and filling var with TEST.
   - 34.4% had `read returning non-zero but filling var with TEST.
   - 32.6% had `read` returning 0 but leaving var empty (which is
   presumably the delayed bare newline after previously filling the var with
   TEST but returning 142).
   - 1.7% were handled by `check_read_timeout()`, and all had read
   returning a status of 142 (and leaving var empty).

I note that 1721+32649-34367=3 so I infer that the last 3 cases are
interconnected:

Of that 1.7% almost all were handled by this section of read.def:
  /* I don't think this clause ever tests true. */
  if (skip_ctlnul && saw_escape && i == 1 && input_string[0] == CTLNUL)
    saw_escape = 0;             /* Avoid dequoting bare CTLNUL */

  input_string[i] = '\0';
*  check_read_timeout ();*

#if defined (READLINE)
  if (edit)
    free (rlbuf);
#endif

-Martin
PS: I've since run other tests that confirm the association I noted above,
but I didn't keep the output. I'll run them again if anyone wants to see a
more precise demonstration.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]