From bug-octave-request at bevo dot che dot wisc dot edu Thu Aug 31 09:10:42 2000 Subject: File ID and file descriptor confusion - the fcntl bug From: Joćo Manuel Rodrigues To: bug-octave at bevo dot che dot wisc dot edu Date: Thu, 31 Aug 2000 15:05:36 +0100 -------- Bug report for Octave 2.0.14 configured for alpha-suse-linux-gnu Description: ----------- The fopen function in Octave returns an integer (the FID) that can be used to refer to the file in other C-style I/O functions like fread, fwrite, etc. One is tempted to think that this FID is equal to the file descriptor (FD) used by the operating system calls open(), read(), write(), etc. Not so! I found this the hard way, while trying to debug an .oct function that calls ioctl() on a device opened by Octave's fopen. Well, while skimming through Octave 2.0.16 source code, I found that the fcntl builtin function is making the same mistake. (Note: I'm running Octave 2.0.14 but I read the 2.0.16 source code which probably is identical in this respect.) Repeat-By: --------- I'm not sure that you can repeat it easily, but you can try running the following script (test.m): fid = fopen(".", "r"); [err,msg] = fcntl(fid, F_GETFD, 0); fclose(fid); through Octave while tracing the system calls with strace (a tool to trace system calls in Linux): strace octave test.m Searching the last lines of output for fcntl, you may find something like: ... open(".", O_RDONLY|0x8000) = 8 gettimeofday({967678780, 119782}, NULL) = 0 fcntl(3, F_GETFD) = 0 gettimeofday({967678780, 121512}, NULL) = 0 close(8) = 0 ... In this case, open(".",...) returns FD=8, but fcntl() uses FD=3, which is in fact the FID returned by fopen. The actual numbers may vary depending on your setup, and it may even happen that FID = FD on a particular trial, but not as a rule. Fix: --- I haven't tried this myself because I don't need fcntl but you certainly must change the fcntl source code in octave-2.0.16/src/syscalls.cc so that instead of: double d_fid = args(0).double_value (); // ... some argument checking code omitted ... int fid = NINT (d_fid); you must have something like: octave_stream *os = octave_stream_list::lookup(args(0)); fid = os->file_number(); In this case, I think lookup takes care of checking args(0) so the argument checking code must be reworked (simplified, actually). Just a few more comments about code legibility: 1) You might consider renaming variable fid as fd in order to stress the difference between "internal" file descriptor and "external" file ID. 2) It's quite annoying that the functions octave_stream_list::get_file_number() and octave_base_stream::file_number() in octave-2.0.16/src/oct-stream.cc have such similar names but refer to different numbers: an FID in the former and an FD in the second. It certainly fooled me for a while. Renaming should be considered. Configuration (please do not edit this section): ----------------------------------------------- uname output: Linux localhost.localdomain 2.2.5-15 #1 Thu Apr 13 21:01:20 WEST 2000 i686 unknown configure opts: --prefix=/usr --exec-prefix=/usr --enable-shared --enable-lite-kernel --host=alpha-suse-linux Fortran compiler: g77 FFLAGS: -O F2C: F2CFLAGS: FLIBS: -lg2c -lm -L/usr/lib/gcc-lib/i486-linux/egcs-2.91.66 -L/usr/i486-linux/lib -lm CPPFLAGS: INCFLAGS: -I/usr/include -I/usr/include/octave-2.0.14 C compiler: gcc, version 2.91.66 19990314/Linux (egcs-1.1.2 release) CFLAGS: -DHAVE_CONFIG_H -D_GNU_SOURCE CPICFLAG: -fPIC C++ compiler: c++, version 2.91.66 19990314/Linux (egcs-1.1.2 release) CXXFLAGS: -DHAVE_CONFIG_H -fno-rtti -fno-exceptions -fno-implicit-templates -D_GNU_SOURCE CXXPICFLAG: -fPIC LDFLAGS: -g LIBFLAGS: -L/usr/lib/octave-2.0.14 RLD_FLAG: -Xlinker -rpath -Xlinker /usr/lib/octave-2.0.14 TERMLIBS: -lncurses LIBS: LEXLIB: LIBPLPLOT: LIBDLFCN: DEFS: -DOCTAVE_SOURCE=1 -DSEPCHAR=':' -DSEPCHAR_STR=":" -DUSE_READLINE=1 -D__NO_MATH_INLINES=1 -DCXX_NEW_FRIEND_TEMPLATE_DECL=1 -DHAVE_LIBM=1 -DF77_APPEND_UNDERSCORE=1 -DOCTAVE_LITE=1 -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DHAVE_ALLOCA_H=1 -DHAVE_ALLOCA=1 -DNPOS=string::npos -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_FNMATCH_H=1 -DHAVE_GLOB_H=1 -DHAVE_GRP_H=1 -DHAVE_LIMITS_H=1 -DHAVE_MEMORY_H=1 -DHAVE_NCURSES_H=1 -DHAVE_PWD_H=1 -DHAVE_SGTTY_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_SYS_PARAM_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_TERMIO_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_VARARGS_H=1 -DHAVE_ATEXIT=1 -DHAVE_BCOPY=1 -DHAVE_BZERO=1 -DHAVE_DUP2=1 -DHAVE_ENDGRENT=1 -DHAVE_ENDPWENT=1 -DHAVE_EXECVP=1 -DHAVE_FCNTL=1 -DHAVE_FORK=1 -DHAVE_GETCWD=1 -DHAVE_GETEGID=1 -DHAVE_GETEUID=1 -DHAVE_GETGID=1 -DHAVE_GETGRENT=1 -DHAVE_GETGRGID=1 -DHAVE_GETGRNAM=1 -DHAVE_GETHOSTNAME=1 -DHAVE_GETPGRP=1 -DHAVE_GETPID=1 -DHAVE_GETPPID=1 -DHAVE_GETPWENT=1 -DHAVE_GETPWNAM=1 -DHAVE_GETPWUID=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_GETUID=1 -DHAVE_GETWD=1 -DHAVE_LSTAT=1 -DHAVE_MEMMOVE=1 -DHAVE_MKDIR=1 -DHAVE_MKFIFO=1 -DHAVE_ON_EXIT=1 -DHAVE_PIPE=1 -DHAVE_PUTENV=1 -DHAVE_RENAME=1 -DHAVE_RINDEX=1 -DHAVE_RMDIR=1 -DHAVE_SETGRENT=1 -DHAVE_SETPWENT=1 -DHAVE_SETVBUF=1 -DHAVE_SIGACTION=1 -DHAVE_SIGPENDING=1 -DHAVE_SIGPROCMASK=1 -DHAVE_SIGSUSPEND=1 -DHAVE_STAT=1 -DHAVE_STRCASECMP=1 -DHAVE_STRDUP=1 -DHAVE_STRERROR=1 -DHAVE_STRNCASECMP=1 -DHAVE_TEMPNAM=1 -DHAVE_UMASK=1 -DHAVE_UNLINK=1 -DHAVE_USLEEP=1 -DHAVE_VFPRINTF=1 -DHAVE_VSPRINTF=1 -DHAVE_WAITPID=1 -DHAVE_PROGRAM_INVOCATION_NAME=1 -DHAVE_LIBDL=1 -DHAVE_DLOPEN=1 -DHAVE_DLSYM=1 -DHAVE_DLERROR=1 -DHAVE_DLCLOSE=1 -DWITH_DL=1 -DWITH_DYNAMIC_LINKING=1 -DHAVE_FINITE=1 -DHAVE_ISNAN=1 -DHAVE_ISINF=1 -DHAVE_ACOSH=1 -DHAVE_ASINH=1 -DHAVE_ATANH=1 -DHAVE_ERF=1 -DHAVE_ERFC=1 -DHAVE_ST_BLKSIZE=1 -DHAVE_ST_BLOCKS=1 -DHAVE_ST_RDEV=1 -DHAVE_TM_ZONE=1 -DHAVE_GR_PASSWD=1 -DEXCEPTION_IN_MATH=1 -DRETSIGTYPE=void -DSYS_SIGLIST_DECLARED=1 -DHAVE_SYS_SIGLIST=1 -DHAVE_POSIX_SIGNALS=1 -DHAVE_GETRUSAGE=1 -DHAVE_TIMES=1 User-preferences (please do not edit this section): -------------------------------------------------- EDITOR = "vi" EXEC_PATH = ":/usr/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin:/bin:/usr/X11R6/bin:/home/jmr/bin:/usr/X11R6/bin:/home/jmr/bin" IMAGEPATH = ".:/usr/share/octave/2.0.14/imagelib//" INFO_FILE = "/usr/info/octave.info" INFO_PROGRAM = "info" LOADPATH = "::~/octave//" PAGER = "less -e -P'-- less ?pB(%pB\\%):--. (f)orward, (b)ack, (q)uit$'" PS1 = "\\s:\\#> " PS2 = "> " PS4 = "+ " auto_unload_dot_oct_files = 0 automatic_replot = 0 beep_on_error = 0 completion_append_char = " " default_eval_print_flag = 1 # default_global_variable_value = default_return_value = [] default_save_format = "ascii" define_all_return_values = 0 do_fortran_indexing = 0 echo_executing_commands = 0 empty_list_elements_ok = "warn" fixed_point_format = 0 gnuplot_binary = "gnuplot" gnuplot_has_frames = 1 gnuplot_has_multiplot = 1 history_file = "/home/jmr/.octave_hist" history_size = 1024 ignore_function_time_stamp = "system" implicit_num_to_str_ok = 0 implicit_str_to_num_ok = 0 initialize_global_variables = 0 max_recursion_depth = 256 ok_to_lose_imaginary_part = "warn" output_max_field_width = 10 output_precision = 5 page_output_immediately = 0 page_screen_output = 1 prefer_column_vectors = 1 prefer_zero_one_indexing = 0 print_answer_id_name = 1 print_empty_dimensions = 1 propagate_empty_matrices = 1 resize_on_range_error = 1 return_last_computed_value = 0 save_precision = 15 saving_history = 1 silent_functions = 0 split_long_rows = 1 string_fill_char = " " struct_levels_to_print = 2 suppress_verbose_help_message = 0 treat_neg_dim_as_zero = 0 warn_assign_as_truth_value = 1 warn_comma_in_global_decl = 1 warn_divide_by_zero = 1 warn_function_name_clash = 1 warn_missing_semicolon = 0 warn_reload_forces_clear = 1 warn_variable_switch_label = 0 whitespace_in_literal_matrix = I hope this helps. Keep up the good work. -- Joao Manuel Rodrigues Dep. Electronica e Telecom. / IEETA Universidade de Aveiro, Portugal ----------------------------------------------------------------------- Octave is freely available under the terms of the GNU GPL. Octave's home on the web: http://www.che.wisc.edu/octave/octave.html How to fund new projects: http://www.che.wisc.edu/octave/funding.html Subscription information: http://www.che.wisc.edu/octave/archive.html -----------------------------------------------------------------------