bugGNU Octave - Bugs: bug #33330, fgets hangs octave when reading...

 
 

bug #33330: fgets hangs octave when reading newline

Submitter:  Carnë Draug <carandraug>
Submitted:  Tue 17 May 2011 02:24:03 PM UTC
   
 
Category:  Libraries Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Matlab Compatibility
Status:  Wont Fix Assigned to:  None
Originator Name:  Open/Closed:  * Closed
Release:  * 3.2.4 Operating System:  * GNU/Linux
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Mon 29 Jul 2013 05:02:05 AM UTC, comment #8: 

Check Matlab's own documentation on this (http://www.mathworks.com/help/matlab/import_export/import-text-data-files-with-low-level-io.html?#br4ssin).

In particular, I see:

"After each read operation, fgetl and fgets check the next character in the file for the end-of-file marker. Therefore, these functions sometimes set the end-of-file indicator before they return a value of -1."

and

"This behavior does not conform to the ANSI specifications for the related C language functions"

So, I think we have to keep it.  We could restrict this only to files, rather than sockets, if there is an easy way to tell that


Rik <rik5>
Group administrator
Sat 27 Jul 2013 10:06:56 PM UTC, comment #7: 

This bug is still open, so what needs to be done to verify if the hack listed in comment #1 is still needed for Matlab compatibility?

Mike Miller <mtmiller>
Group Member
Wed 18 May 2011 11:14:51 AM UTC, comment #6: 

Thank you so much Rik! For both the code and the explanation on how it works. I tried the code and now does exactly what I wanted.

I learn so much when using octave, really enjoy it and all thanks to people like you who take their time to explain this stuff and of corse to write octave as well. Thanks again

Carnë Draug <carandraug>
Group Member
Wed 18 May 2011 04:04:21 AM UTC, comment #5: 

The 'hang' is not really a hang.  When you do a read on a socket and there is nothing available the operating system has two choices.  The default is blocking I/O which means the process stops and waits for input.  For example, when you call zenity from a bash command line it stops and waits for you to do something with the graphical object.  It doesn't just return to the prompt and allow you to continue typing.  Octave is operating the same way.  If you must, you can tell the operating system that you want non-blocking I/O in which case any call to read something from the socket will return immediately if there is nothing there.  However, you shouldn't build this into a tight polling loop.  Don't try something like the loop below.


while (isempty (fscanf (fid, '%s', 'C')))
  sleep (1);
endwhile


If you do need to change to non-blocking mode you can use the fcntl() function like so


fcntl (fid, F_SETFL, O_NONBLOCK);


in which case a read on an empty socket will return [] immediately.

Rik <rik5>
Group administrator
Wed 18 May 2011 12:50:38 AM UTC, comment #4: 

Thanks. This will at least read the last selected value (instead of the one before) but still hangs if the last selected value has already been read.

octave-3.2.3:26> fid = popen("zenity --scale --print-partial", "r");
## zenity scale dialog shows up
## move the  bar
octave-3.2.3:27> str = fscanf (fid, "%s", 'C')
str =27
octave-3.2.3:28> str = fscanf (fid, "%s", 'C')
## octave hangs. Does not return empty matrix
## move the bar
str = 46
## close dialog (press OK)
octave-3.2.3:29> str = fscanf (fid, "%s", 'C')
str = 46
## this is expected since the selected should be printed to the pipe again after pressing OK


Thanks in advance

Carnë Draug <carandraug>
Group Member
Tue 17 May 2011 11:48:01 PM UTC, comment #3: 

Try the following


str = fscanf (fid, "%s", 'C');


It works for me with the zenity example you posted.  Beware that you'll no longer get -1 on a closed dialog, but rather the empty matrix [].

Rik <rik5>
Group administrator
Tue 17 May 2011 11:04:53 PM UTC, comment #2: 

Hi

thanks for looking into this so quickly. I appreciate it immensely.

Building from a modified source is not an option for me since this is code for the zenity package on octave-forge. Is there any other workaround that I can do on my code? The current implementation of zenity_scale is pretty useless without being able to read the values.

If this is a bug on Matlab, shouldn't octave fix it before Matlab instead of trying to mimic the defective behavior of them until they fix it?

Carnë Draug <carandraug>
Group Member
Tue 17 May 2011 08:17:37 PM UTC, comment #1: 

Confirmed.  The problem seems to be an attempt to mimic Matlab's behavior exactly.  In this case it forces a kludge which works with files, which are non-blocking I/O, but fails with pipes where the process blocks and waits for new input.

If you are building from source, the solution is to comment out the kludge which begins at line 988 of the file oct-stream.cc and encompasses this stanza


if (! is.eof () && char_count > 0)
  {
    // GAGME.  Matlab seems to check for EOF even if the last
    // character in a file is a newline character.  This is NOT
    // what the corresponding C-library functions do.
    int disgusting_compatibility_hack = is.get ();
    if (! is.eof ())
      is.putback (disgusting_compatibility_hack);
  }


I'll also post something to the octave-maintainers mailing list.  It may be that Matlab has changed and we can ditch this hack entirely.

Rik <rik5>
Group administrator
Tue 17 May 2011 02:24:03 PM UTC, original submission:  

Bug report for Octave 3.2.4 configured for i486-pc-linux-gnu

Description:
-----------
If my understanding is correct, octave should return -1 when there's nothing else to read. When using fgets with at least zenity, it seems to hang. The problem seems to be on the last character (n) as can be shown by reading one character at a time.

Repeat-By:
---------
## this will open a dialog box with a progress bar that can be
## moved. Every time the bar is moved the value where it stops
## should be printed
octave-3.2.4 > fid = popen("zenity --scale --print-partial", "r")
## adjust bar to value 16
## adjust bar to value 24
octave-3.2.4 > fgets(fid)
ans = 16

octave-3.2.4 > fgets(fid)
## octave hangs here
## adjust bar to value 46
ans = 24

octave-3.2.4 > fgets(fid)
## octave hangs here
## press OK on the zenity dialog
ans = 46

This example shows the problem being on the last character of the
value by using fgets to read one character at a time

octave-3.2.4 > fid = popen("zenity --scale --print-partial", "r")
## adjust bar to value 16
octave-3.2.4 > fgets(fid,1)
ans = 1
octave-3.2.4 > fgets(fid,1)
ans = 6
octave-3.2.4 > fgets(fid,1)
## octave hangs here instead of returning -1

This shows that zenity works fine in bash
$ zenity --scale --print-partial
## move bar to 16
16

## move bar to 27
27

## move bar to 54
54

## press ok


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

uname output:     Linux altar 2.6.32-5-686 #1 SMP Tue Mar 8 21:36:00 UTC 2011 i686 GNU/Linux
configure opts:   '--build=i486-linux-gnu' '--prefix=/usr' '--datadir=/usr/share' '--libdir=/usr/lib' '--libexecdir=/usr/lib' '--infodir=/usr/share/info' '--mandir=/usr/share/man' '--with-blas=-lblas-3gf' '--with-lapack=-llapackgf-3' '--with-hdf5' '--with-fftw' '--enable-shared' '--enable-rpath' '--disable-static' 'build_alias=i486-linux-gnu' 'CC=gcc' 'CFLAGS=-g -O2' 'LDFLAGS=' 'CPPFLAGS=' 'CXX=g++' 'CXXFLAGS=-g -O2' 'F77=gfortran' 'FFLAGS=-g -O2'
Fortran compiler: gfortran
FFLAGS:           -O2 -g
FLIBS:            -lgfortranbegin -lgfortran
CPPFLAGS:        
INCFLAGS:         -I. -I. -I./liboctave -I./src -I./libcruft/misc
C compiler:       gcc, version 4.4.5 (Debian 4.4.5-5)
CFLAGS:           -O2 -g
CPICFLAG:         -fPIC
C++ compiler:     g++, version 4.4.5
CXXFLAGS:         -O2 -g
CXXPICFLAG:       -fPIC
LD_CXX:           g++
LDFLAGS:         
LIBFLAGS:         -L.
RLD_FLAG:         -Wl,-rpath -Wl,/usr/lib/octave-3.2.4
BLAS_LIBS:        -llapack -lblas
FFTW_LIBS:        -lfftw3 -lfftw3f
LIBS:             -lreadline  -lncurses -ldl -lhdf5 -lz -lm
LEXLIB:          
LIBGLOB:         
SED:              /bin/sed
DEFS:

  -DPACKAGE_NAME="" -DPACKAGE_TARNAME="" -DPACKAGE_VERSION=""
  -DPACKAGE_STRING="" -DPACKAGE_BUGREPORT="" -DPACKAGE_URL=""
  -DOCTAVE_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_ALL_SOURCE=1 -D_GNU_SOURCE=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_PTHREAD=1 -DHAVE_X_WINDOWS=1
  -DHAVE_LIBM=1 -DHAVE_QHULL=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_GLPK_H=1 -DHAVE_GLPK=1 -DHAVE_CURL_CURL_H=1
  -DHAVE_CURL=1 -DHAVE_MAGICK=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_QRUPDATE=1
  -DHAVE_SUITESPARSE_AMD_H=1 -DHAVE_AMD=1 -DHAVE_SUITESPARSE_UMFPACK_H=1
  -DHAVE_UMFPACK=1 -DUMFPACK_SEPARATE_SPLIT=1 -DHAVE_SUITESPARSE_COLAMD_H=1
  -DHAVE_COLAMD=1 -DHAVE_SUITESPARSE_CCOLAMD_H=1 -DHAVE_CCOLAMD=1
  -DHAVE_SUITESPARSE_CHOLMOD_H=1 -DHAVE_CHOLMOD=1 -DHAVE_SUITESPARSE_CS_H=1
  -DHAVE_CXSPARSE=1 -DHAVE_ARPACK=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/lib/octave/3.2.4/site/exec/i486-pc-linux-gnu:/usr/lib/octave/api-v37/site/exec/i486-pc-linux-gnu:/usr/lib/octave/site/exec/i486-pc-linux-gnu:/usr/lib/octave/3.2.4/exec/i486-pc-linux-gnu:/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/games
  IMAGE_PATH = .:/usr/share/octave/3.2.4/imagelib
  PAGER = pager
  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/carandraug/.octave_hist
  history_size = 1024
  ignore_function_time_stamp = system
  info_file = /usr/share/info/octave3.2.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

Carnë Draug <carandraug>
Group Member

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by mtmiller (Posted a comment)
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by carandraug (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 5 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2013-07-29 rik5 StatusConfirmed Wont Fix
        Open/ClosedOpen Closed
    2013-07-27 mtmiller CategoryNone Libraries
        Item GroupNone Matlab Compatibility
    2011-05-17 rik5 StatusNone Confirmed

    Back to the top

    Powered by Savane 3.13-f8d8.
    Corresponding source code