kbhit() with nowait option misses characters.

Joe Rothweiler octaveuser at sensicomm.com
Tue Jun 30 15:31:50 CDT 2009


Bug report for Octave 3.2.0 configured for i686-pc-linux-gnu

Description:
-----------
  I'm trying to use the kbhit builtin function under Linux in
  nowait mode: c1=kbhit(1); It is
  supposed to return a character if a key has been hit,
  else return an empty string. In fact, it often
  returns an empty string even if a key has been hit.

  Here's what I think is happening:
  in src/sysdep.cc, if macro HAVE__KBHIT is not defined,
  then subroutine octave_kbhit () calls
  raw_mode(...) at line 515. In turn, raw_mode
  calls tcsetattr (tty_fd, TCSAFLUSH, &s) at line 395.

  Per the tcsetattr man page:
  "TCSAFLUSH ... all  input  that  has  been received but
  not read will be discarded"

  So, input keystrokes will be lost unless they occur
  after the call to tcsetattr but before the read at
  line 531.

Repeat-By:
---------

  ------ Test file keytest.m:
  while 1
    c1=kbhit(1);
    if (~isempty(c1))
      fprintf(2,'got %s\n',c1);
      break;
    end
  end
  ------
  Execute using: octave -q -i keytest.m
  then hit any keyboard key, say 'q'. Output should be:
  qgot q
  (where the first q is the input being echoed).
  Actual output is
  qqqqqgot q
  (ie, the key must be struck several times before
  it is detected).


Fix:
---
In src/sysdep.cc, subroutine raw_mode, line 395:
TCSAFLUSH should be TCSADRAIN.
(This makes kbhit() work correctly; I don't know
if raw_mode is called anywhere else.)

Configuration (please do not edit this section):
-----------------------------------------------

uname output:     Linux caspian 2.6.22-2-k7 #1 SMP Fri Aug 31 01:02:37
UTC 2007 i686 GNU/Linux
configure opts:
Fortran compiler: gfortran
FFLAGS:           -O -mieee-fp
FLIBS:            -L/usr/lib/gcc/i486-linux-gnu/4.3.3
-L/usr/lib/gcc/i486-linux-gnu/4.3.3/../../../../lib -L/lib/../lib
-L/usr/lib/../lib -L/usr/lib/gcc/i486-linux-gnu/4.3.3/../../..
-L/usr/lib/i486-linux-gnu -lhdf5 -lz -lgfortranbegin -lgfortran -lm
CPPFLAGS:
INCFLAGS:         -I. -I. -I./liboctave -I./src -I./libcruft/misc
C compiler:       gcc, version 4.3.3 (Debian 4.3.3-10)
CFLAGS:           -g -O2
CPICFLAG:         -fPIC
C++ compiler:     g++, version 4.3.3
CXXFLAGS:         -g -O2
CXXPICFLAG:       -fPIC
LD_CXX:           g++
LDFLAGS:
LIBFLAGS:         -L.
RLD_FLAG:         -Wl,-rpath -Wl,/usr/local/lib/octave-3.2.0
BLAS_LIBS:        -llapack -lblas
FFTW_LIBS:        -lfftw3 -lfftw3f
LIBS:             -lreadline  -lncurses -ldl -lblas -lhdf5 -lz -lm
LEXLIB:
LIBGLOB:
SED:              /bin/sed
DEFS:

  -DPACKAGE_NAME="" -DPACKAGE_TARNAME="" -DPACKAGE_VERSION=""
  -DPACKAGE_STRING="" -DPACKAGE_BUGREPORT="" -DOCTAVE_SOURCE=1
  -D_GNU_SOURCE=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1
  -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1
  -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -D__EXTENSIONS__=1
  -D_POSIX_PTHREAD_SEMANTICS=1 -D_TANDEM_SOURCE=1 -DSEPCHAR=':'
  -DSEPCHAR_STR=":" -D__NO_MATH_INLINES=1 -DCXX_NEW_FRIEND_TEMPLATE_DECL=1
  -DCXX_ISO_COMPLIANT_LIBRARY=1 -DHAVE_X_WINDOWS=1 -DHAVE_LIBM=1
  -DHAVE_PCRE_COMPILE=1 -DHAVE_PCRE=1 -DHAVE_REGEXEC=1 -DHAVE_REGEX=1
  -DHAVE_ZLIB_H=1 -DHAVE_ZLIB=1 -DHAVE_HDF5_H=1 -DHAVE_HDF5=1
  -DHAVE_H5GGET_NUM_OBJS=1 -DHAVE_FFTW3=1 -DHAVE_GL_GL_H=1 -DHAVE_GL_GLU_H=1
  -DHAVE_OPENGL=1 -DHAVE_FTGL_FTGL_H=1 -DHAVE_FTGL=1 -DHAVE_FLTK=1
  -DHAVE_IEEE754_DATA_FORMAT=1 -DF77_FUNC(name,NAME)=name ## _
  -DF77_FUNC_(name,NAME)=name ## _ -DHAVE_BLAS=1 -DHAVE_GETHOSTNAME=1
  -DHAVE_GETPWNAM=1 -DHAVE_DEV_T=1 -DHAVE_INO_T=1 -DHAVE_NLINK_T=1
  -DHAVE_NLINK_T=1 -DHAVE_LONG_LONG_INT=1 -DHAVE_UNSIGNED_LONG_LONG_INT=1
  -DHAVE_SIGSET_T=1 -DHAVE_SIG_ATOMIC_T=1 -DSIZEOF_SHORT=2
  -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DSIZEOF_LONG_LONG=8 -DHAVE_ALLOCA_H=1
  -DHAVE_ALLOCA=1 -DHAVE_PLACEMENT_DELETE=1 -DHAVE_DYNAMIC_AUTO_ARRAYS=1
  -DHAVE_FAST_INT_OPS=1 -DSIZEOF_LONG_DOUBLE=12 -DSTDC_HEADERS=1
  -DHAVE_DIRENT_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_SYS_WAIT_H=1
  -DHAVE_ASSERT_H=1 -DHAVE_CURSES_H=1 -DHAVE_DLFCN_H=1 -DHAVE_FCNTL_H=1
  -DHAVE_FLOAT_H=1 -DHAVE_GRP_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_LIMITS_H=1
  -DHAVE_LOCALE_H=1 -DHAVE_MEMORY_H=1 -DHAVE_NCURSES_H=1 -DHAVE_POLL_H=1
  -DHAVE_PTHREAD_H=1 -DHAVE_PWD_H=1 -DHAVE_STDINT_H=1 -DHAVE_STDLIB_H=1
  -DHAVE_STRING_H=1 -DHAVE_SYS_IOCTL_H=1 -DHAVE_SYS_PARAM_H=1
  -DHAVE_SYS_POLL_H=1 -DHAVE_SYS_RESOURCE_H=1 -DHAVE_SYS_SELECT_H=1
  -DHAVE_SYS_STAT_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_TIMES_H=1
  -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_UTSNAME_H=1 -DHAVE_TERMCAP_H=1
  -DHAVE_UNISTD_H=1 -DHAVE_UTIME_H=1 -DHAVE_SSTREAM=1 -DHAVE_TERMIOS_H=1
  -DHAVE_TERMIO_H=1 -DHAVE_SGTTY_H=1 -DHAVE_GLOB_H=1 -DHAVE_FNMATCH_H=1
  -DHAVE_FNMATCH=1 -DHAVE_GLOB=1 -DHAVE_ATEXIT=1 -DHAVE_BASENAME=1
  -DHAVE_BCOPY=1 -DHAVE_BZERO=1 -DHAVE_CANONICALIZE_FILE_NAME=1
  -DHAVE_CHMOD=1 -DHAVE_DUP2=1 -DHAVE_ENDGRENT=1 -DHAVE_ENDPWENT=1
  -DHAVE_EXECVP=1 -DHAVE_EXPM1=1 -DHAVE_EXPM1F=1 -DHAVE_FCNTL=1
  -DHAVE_FORK=1 -DHAVE_FSTAT=1 -DHAVE_GETCWD=1 -DHAVE_GETEGID=1
  -DHAVE_GETEUID=1 -DHAVE_GETGID=1 -DHAVE_GETGRENT=1 -DHAVE_GETGRGID=1
  -DHAVE_GETGRNAM=1 -DHAVE_GETPGRP=1 -DHAVE_GETPID=1 -DHAVE_GETPPID=1
  -DHAVE_GETPWENT=1 -DHAVE_GETPWUID=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_GETUID=1
  -DHAVE_GETWD=1 -DHAVE_KILL=1 -DHAVE_LGAMMA=1 -DHAVE_LGAMMAF=1
  -DHAVE_LGAMMA_R=1 -DHAVE_LGAMMAF_R=1 -DHAVE_LINK=1 -DHAVE_LOCALTIME_R=1
  -DHAVE_LOG1P=1 -DHAVE_LOG1PF=1 -DHAVE_LSTAT=1 -DHAVE_MEMMOVE=1
  -DHAVE_MKDIR=1 -DHAVE_MKFIFO=1 -DHAVE_MKSTEMP=1 -DHAVE_ON_EXIT=1
  -DHAVE_PIPE=1 -DHAVE_POLL=1 -DHAVE_PUTENV=1 -DHAVE_RAISE=1
  -DHAVE_READLINK=1 -DHAVE_REALPATH=1 -DHAVE_RENAME=1 -DHAVE_RINDEX=1
  -DHAVE_RMDIR=1 -DHAVE_ROUNDL=1 -DHAVE_SELECT=1 -DHAVE_SETGRENT=1
  -DHAVE_SETLOCALE=1 -DHAVE_SETPWENT=1 -DHAVE_SETVBUF=1 -DHAVE_SIGACTION=1
  -DHAVE_SIGLONGJMP=1 -DHAVE_SIGPENDING=1 -DHAVE_SIGPROCMASK=1
  -DHAVE_SIGSUSPEND=1 -DHAVE_SNPRINTF=1 -DHAVE_STAT=1 -DHAVE_STRCASECMP=1
  -DHAVE_STRDUP=1 -DHAVE_STRERROR=1 -DHAVE_STRNCASECMP=1 -DHAVE_STRPTIME=1
  -DHAVE_STRSIGNAL=1 -DHAVE_SYMLINK=1 -DHAVE_TEMPNAM=1 -DHAVE_TGAMMAF=1
  -DHAVE_TRUNC=1 -DHAVE_UMASK=1 -DHAVE_UNAME=1 -DHAVE_UNLINK=1
  -DHAVE_USLEEP=1 -DHAVE_UTIME=1 -DHAVE_VFPRINTF=1 -DHAVE_VSPRINTF=1
  -DHAVE_VSNPRINTF=1 -DHAVE_WAITPID=1 -DHAVE_DECL_EXP2=1 -DHAVE_DECL_ROUND=1
  -DHAVE_DECL_TGAMMA=1 -DHAVE_EXP2=1 -DHAVE_ROUND=1 -DHAVE_TGAMMA=1
  -DHAVE_STRFTIME=1 -DHAVE_C99_VSNPRINTF=1 -DHAVE_LIBDL=1 -DHAVE_DLOPEN=1
  -DHAVE_DLSYM=1 -DHAVE_DLERROR=1 -DHAVE_DLCLOSE=1 -DHAVE_DLOPEN_API=1
  -DENABLE_DYNAMIC_LINKING=1 -DHAVE_TIMEVAL=1 -DHAVE_CMATH_ISNAN=1
  -DHAVE_CMATH_ISNANF=1 -DHAVE_CMATH_ISINF=1 -DHAVE_CMATH_ISINFF=1
  -DHAVE_CMATH_ISFINITE=1 -DHAVE_CMATH_ISFINITEF=1 -DHAVE_FINITE=1
  -DHAVE_ISNAN=1 -DHAVE_ISINF=1 -DHAVE_COPYSIGN=1 -DHAVE_DECL_SIGNBIT=1
  -DHAVE_ACOSH=1 -DHAVE_ACOSHF=1 -DHAVE_ASINH=1 -DHAVE_ASINHF=1
  -DHAVE_ATANH=1 -DHAVE_ATANHF=1 -DHAVE_ERF=1 -DHAVE_ERFF=1 -DHAVE_ERFC=1
  -DHAVE_ERFCF=1 -DHAVE_EXP2F=1 -DHAVE_LOG2=1 -DHAVE_LOG2F=1 -DHAVE_HYPOTF=1
  -DHAVE_STRUCT_STAT_ST_BLKSIZE=1 -DHAVE_STRUCT_STAT_ST_BLOCKS=1
  -DHAVE_STRUCT_STAT_ST_RDEV=1 -DHAVE_STRUCT_TM_TM_ZONE=1
  -DHAVE_TM_ZONE=1 -DUSE_READLINE=1 -DEXCEPTION_IN_MATH=1 -DRETSIGTYPE=void
  -DHAVE_DECL_SYS_SIGLIST=1 -DHAVE_POSIX_SIGNALS=1 -DRETSIGTYPE_IS_VOID=1
  -DHAVE_GETRUSAGE=1 -DHAVE_TIMES=1 -DYYTEXT_POINTER=1

User-preferences (please do not edit this section):
--------------------------------------------------

  EDITOR = emacs
  EXEC_PATH =
/usr/local/libexec/octave/3.2.0/site/exec/i686-pc-linux-gnu:/usr/local/libexec/octave/api-v37/site/exec/i686-pc-linux-gnu:/usr/local/libexec/octave/site/exec/i686-pc-linux-gnu:/usr/local/libexec/octave/3.2.0/exec/i686-pc-linux-gnu:/usr/local/bin:.:/home/jrothwei/share/bin:/home/jrothwei/i386/bin:/home/jrothwei/olds:/usr/local/bin:/usr/bin:/bin:/usr/games
  IMAGE_PATH = .:/usr/local/share/octave/3.2.0/imagelib
  PAGER = less
  PS1 = \s:\#>
  PS2 = >
  PS4 = +
  beep_on_error = 0
  completion_append_char =
  crash_dumps_octave_core = 1
  echo_executing_commands = 0
  fixed_point_format = 0
  gnuplot_binary = gnuplot
# gnuplot_command_end = <no value or error in displaying it>
# gnuplot_command_plot = <no value or error in displaying it>
# gnuplot_command_replot = <no value or error in displaying it>
# gnuplot_command_splot = <no value or error in displaying it>
# gnuplot_command_title = <no value or error in displaying it>
# gnuplot_command_using = <no value or error in displaying it>
# gnuplot_command_with = <no value or error in displaying it>
  history_file = /home/jrothwei/.octave_hist
  history_size = 1024
  ignore_function_time_stamp = system
  info_file = /usr/local/share/info/octave.info
  info_program = info
  makeinfo_program = makeinfo
  max_recursion_depth = 256
  output_max_field_width = 5
  output_precision = 5
  page_output_immediately = 0
  page_screen_output = 1
# print_answer_id_name = <no value or error in displaying it>
  print_empty_dimensions = 1
  save_precision = 16
  saving_history = 1
  sighup_dumps_octave_core = 1
  sigterm_dumps_octave_core = 1
  silent_functions = 0
  split_long_rows = 1
  string_fill_char =
  struct_levels_to_print = 2
  suppress_verbose_help_message = 0






More information about the Bug-octave mailing list