bugGNU Octave - Bugs: bug #66399, fseek and ftell functions don't...

 
 

bug #66399: fseek and ftell functions don't always work correctly on Win11 with filesizes >2GB

Submitter:  MikeMcC <mmccully>
Submitted:  Sat 02 Nov 2024 10:56:24 PM UTC
   
 
Category:  Octave Function Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Unexpected Error or Warning
Status:  Ready For Test Assigned to:  None
Originator Name:  Open/Closed:  * Open
Release:  * 9.2.0 Operating System:  * Microsoft Windows
Fixed Release:  None Planned Release:  10.1.0 (current default)
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Sat 30 Nov 2024 01:04:30 AM UTC, comment #26: 

Okay, thanks for the pointers.  I'll try one of them.

Regarding my comments, I assumed if the fault was in gnulib, then I could rebuild and install it separately.  I've had to rebuild bits and pieces of packages where something wasn't working (and source code was available), but it's been a while, and it was under Linux, not Windows.

MikeMcC <mmccully>
Tue 26 Nov 2024 09:28:10 AM UTC, comment #25: 

Gnulib was updated to a newer version on the default branch of the Octave repository. That will probably be used to eventually release Octave 10.x.

Not sure what you mean by "updating gnulib on my computer". Gnulib is more like a build-time dependency (not a dependency that can be updated after the Octave binaries have been built). So, you'd need to build Octave yourself if you'd like to update to a newer gnulib version before Octave 10 will be released.
Alternatively, you could use the build artifacts of the Windows CI on GitHub to test an un-stable build from the default branch of the Octave repository:
https://wiki.octave.org/Continuous_Build#GitHub_build_artifacts

Markus Mützel <mmuetzel>
Group administrator
Tue 26 Nov 2024 06:07:19 AM UTC, comment #24: 

I suppose it can be closed if updating gnulib fixes it, but it wasn't clear to me from the comments that updating gnulib completely fixed the issue for everyone, so I was waiting for an interim release of Octave to test the the problem and make comments.  That is, in the comments, there was talk of including a fix in 9.3.0 and 10.1.0.  I'm running 9.2.0, which is where I discovered this problem, and 9.2.0 is the current download for Windows.
I'll look into updating gnulib on my computer, but I have other things going at present, and for the purposes of what I'm doing with Octave, we have been able to keep the file sizes under 2GB as a workaround.

MikeMcC <mmccully>
Mon 25 Nov 2024 09:31:48 PM UTC, comment #23: 

Can this bug be closed?  It seems that the original bug report, about fseek and ftell, has been fixed by updating gnulib.  However, this may have created new and different problems.  If the original issue is fixed then I think this report should be closed.

Rik <rik5>
Group administrator
Fri 15 Nov 2024 05:53:10 PM UTC, comment #22: 
Markus Mützel <mmuetzel>
Group administrator
Fri 15 Nov 2024 05:48:20 PM UTC, comment #21: 

OK. Can you open a separate bug report about MacOS failure.
I should be able to get my hands on Mac soon.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Fri 15 Nov 2024 05:46:59 PM UTC, comment #20: 

Oops. That should have read: "They are still passing on macOS 13."

Markus Mützel <mmuetzel>
Group administrator
Fri 15 Nov 2024 05:44:48 PM UTC, comment #19: 

Some tests have started to fail on macOS 14 after updating gnulib:
https://github.com/gnu-octave/octave/actions/runs/11843167971/job/33003488322#step:13:67271

>>>>> processing /Users/runner/work/octave/octave/test/file-encoding/file-encoding.tst
***** test
 help_str = get_help_text ("test_CP1252");
 ## The help text contains the string "ÄÖÜäöü ŠŽšž".  Compare to the
 ## corresponding UTF-8 byte sequence to make sure this test is independent
 ## of how this .tst file is interpreted.
 ref_str = char ([195 132 195 150 195 156 195 164 195 182 195 188 32 ...
                  197 160 197 189 197 161 197 190]);
 assert (strfind (help_str, ref_str));
!!!!! test failed
file_reader::get_input: converting from codepage 'windows-1252' to UTF-8: Function not implemented
***** test
 path_orig = path ();
 unwind_protect
   addpath ("CP1251");
   help_str = get_help_text ("test_CP1251");
   ## The help text contains the string "ДЦЬдць ЉЋљћ".  Compare to the
   ## corresponding UTF-8 byte sequence to make sure this test is independent
   ## of how this .tst of how this .tst file is interpreted.
   ref_str = char ([208 148 208 166 208 172 208 180 209 134 209 140 32 ...
                    208 137 208 139 209 153 209 155]);
   assert (strfind (help_str, ref_str));
 unwind_protect_cleanup
   path (path_orig);
   dir_encoding (canonicalize_file_name ("CP1251"), "delete");
 end_unwind_protect
!!!!! test failed
file_reader::get_input: converting from codepage 'windows-1251' to UTF-8: Function not implemented
***** test
 clear all;  # make sure files are re-parsed
 path_orig = path ();
 unwind_protect
   addpath (canonicalize_file_name ("CP1251"));
   help_str = get_help_text ("test_CP1251");
   ## The help text contains the string "ДЦЬдць ЉЋљћ".  Compare to the UTF-8
   ## byte sequence to make sure this test is independent of how this .tst
   ## file is interpreted.
   ref_str = char ([208 148 208 166 208 172 208 180 209 134 209 140 32 ...
                    208 137 208 139 209 153 209 155]);
   assert (strfind (help_str, ref_str));
 unwind_protect_cleanup
   path (path_orig);
   dir_encoding (canonicalize_file_name ("CP1251"), "delete");
 end_unwind_protect
!!!!! test failed
file_reader::get_input: converting from codepage 'windows-1251' to UTF-8: Function not implemented
***** test <*62780>
 ## wrap in "evalc" to suppress output to the log
 evalc ('oruntests (".");');
!!!!! regression: https://octave.org/testfailure/?62780
native2unicode: iconv() is not supported.  Installing GNU libiconv and then re-compiling Octave could fix this.
***** test <*62780>
 unwind_protect
   dir_encoding (canonicalize_file_name ("CP1251"), "windows-1251");
   ## use "evalc" to suppress output to the log
   evalc ('oruntests ("CP1251");');
 unwind_protect_cleanup
   dir_encoding (canonicalize_file_name ("CP1251"), "delete");
 end_unwind_protect
!!!!! regression: https://octave.org/testfailure/?62780
native2unicode: iconv() is not supported.  Installing GNU libiconv and then re-compiling Octave could fix this.
***** test <*62780>
 old_mfile_encoding = mfile_encoding ("windows-1251");
 unwind_protect
   ## use "evalc" to suppress output to the log
   evalc ('oruntests ("CP1251");');
 unwind_protect_cleanup
   mfile_encoding (old_mfile_encoding);
 end_unwind_protect
!!!!! regression: https://octave.org/testfailure/?62780
native2unicode: iconv() is not supported.  Installing GNU libiconv and then re-compiling Octave could fix this.
***** test <*62780>
 path_orig = path ();
 unwind_protect
   addpath (canonicalize_file_name ("CP1251"));
   ## use "evalc" to suppress output to the log
   evalc ('oruntests ("CP1251");');
 unwind_protect_cleanup
   path (path_orig);
   dir_encoding (canonicalize_file_name ("CP1251"), "delete");
 end_unwind_protect
!!!!! regression: https://octave.org/testfailure/?62780
native2unicode: iconv() is not supported.  Installing GNU libiconv and then re-compiling Octave could fix this.


They are still passing on macOS 14.

I don't have access to a macOS system and can't tell whether that is related to the update or not. But we might just be trading a bug on one platform for a different bug on another platform if we update now...

Markus Mützel <mmuetzel>
Group administrator
Fri 15 Nov 2024 05:34:47 PM UTC, comment #18: 

I understand not updating for the sake of staying with the latest version, but now we have an actual bug affecting octave.
I vote to update.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Fri 15 Nov 2024 05:30:39 PM UTC, comment #17: 

We usually try to not update gnulib for minor releases.
I don't know if this warrants an exception.

Markus Mützel <mmuetzel>
Group administrator
Fri 15 Nov 2024 04:56:06 PM UTC, comment #16: 

Should it go to 9.3 as well?

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Thu 14 Nov 2024 06:21:48 PM UTC, comment #15: 

Bruno Haible fixed the issues with large files on Windows in gnulib.

I updated gnulib in Octave to a commit that contains these changes:
https://hg.savannah.gnu.org/hgweb/octave/rev/226a392f0818

Marking as ready for test.

Markus Mützel <mmuetzel>
Group administrator
Wed 13 Nov 2024 11:58:07 AM UTC, comment #14: 

Thank you again for the feedback.

Not using the wrapper functions in gl2ps-print.cc was probably just an oversight.

I pushed the following changes to explicitly request the "ftello" and "fseeko" modules and to use the wrappers in gl2ps-print.cc:
https://hg.savannah.gnu.org/hgweb/octave/rev/deb0ae92379e
https://hg.savannah.gnu.org/hgweb/octave/rev/99a5580d37ff

(The UNIX terminal sources aren't built on Windows. I'll look into them later.)

As expected, that didn't make a difference for the behavior observed here though.

I've sent an email with some findings to the gnulib mailing list. Maybe, that will help to further track this down.

Markus Mützel <mmuetzel>
Group administrator
Tue 12 Nov 2024 07:15:41 PM UTC, comment #13: 


> Should we also avoid to use `fseek` with pipes?


C code should avoid fseek; always use fseeko. Although fseek should work with small-enough offsets why ask for trouble?

If you use fseeko on a pipe, it should either work (if it's a small seek that stays within the I/O buffer) or fail with errno=ESPIPE; it can also fail for other reasons.

I don't know about std::fseeko, as I don't use C++. However, Gnulib does attempt to make its fseeko replacement visible to C++ using the usual namespace rules. Perhaps this is relevant to your problem, but you'll need a C++ expert to diagnose it.

I see that you do appear to be trying to work around the issue with octave_fseeko_wrapper, which I don't fully understand. If you have that, why use std::fseek in libinterp/corefcn/gl2ps-print.cc? Shouldn't that code use octave_lseeko_wrapper instead?

Bruno Haible knows C++ and MS-Windows (I know neither), and I hope he'll reply again on bug-gnulib and clear up some of the confusion here.

Paul Eggert <eggert>
Tue 12 Nov 2024 06:14:57 PM UTC, comment #12: 

Thank you for re-uploading the patch.

We usually are treating the files in `libgui/qterminal/libqterminal/unix` as "upstream" and try to avoid touching them if not needed.
They are not used when building for Windows. And if I understand correctly, the FILE pointers are pipes in that case.
Should we also avoid to use `fseek` with pipes?

Is `std::fseeko` a part of the C++ standard? Does gnulib also add or replace functions in the `std` namespace?
We generally try to avoid including headers from gnulib directly in C++ sources. (I don't know the exact background. But I seem to recall that it caused issues in some cases in the past.)
Instead, we wrap around gnulib functions in small C objects and call these wrapper functions from C++ code. You'll find, e.g,. `octave_ftello_wrapper` or `octave_fseeko_wrapper` where that is done.
I can try to do that for the changes you proposed for `gl2ps-print.cc`.

I was searching the code base for `fseek` and `ftell`. But I couldn't find places other than the ones you pointed out in your patch where they are used.

Markus Mützel <mmuetzel>
Group administrator
Tue 12 Nov 2024 05:42:27 PM UTC, comment #11: 

I posted the octave-fseeko.diff patch now.

From what you write, this patch won't fix the problem. However, it is a bit of an improvement, as it makes Octave's dependence on fseeko explicit rather than implicit, and it also says explicitly that Octave does not use fseek and ftell (which it should not be doing, though it does in some places other than those mentioned in the patch).

Paul Eggert <eggert>
Tue 12 Nov 2024 05:22:37 AM UTC, comment #10: 

Thank you and Bruno for clarifying and helping out.

It looks like the patch didn't make it into the report. (The preview button ate mine a couple of times in the past. Maybe, that happened to you, too?)
Could you please re-submit it?

Markus Mützel <mmuetzel>
Group administrator
Mon 11 Nov 2024 07:50:34 PM UTC, comment #9: 

As Bruno Haible mentioned on the Gnulib mailing list in "Re: fseek and ftell with large files on Windows", this is not a bug in Gnulib.

To fix the problem, I suppose Octave can use fseeko/ftello internally instead of fseek/ftell, and change its bootstrap.conf to specify the fseeko and ftello modules instead of the fseek and ftell modules.

A quick glance at the source code indicates that Octave is already using fseeko in most places, but there are some places where it's not. I'm attaching a little patch "octave-fseeko.diff" to show the first place I found. Most likely further fixes along these lines would be needed.

Paul Eggert <eggert>
Mon 11 Nov 2024 04:19:13 PM UTC, comment #8: 
Markus Mützel <mmuetzel>
Group administrator
Mon 11 Nov 2024 03:21:49 PM UTC, comment #7: 

Maybe, this is caused by an upstream issue in Gnulib.

Looking only on their code paths for Windows: If I understand their replacement functions for `fseek` and `ftell` correctly, they are effectively calling `_fseeki64` and `_ftelli64` if the `off_t` type is smaller than 64-bit and `fseek` and `ftell` otherwise.
However, even if the `off_t` type is 64-bit (or larger), `fseek` and `ftell` still return `long` on Windows which is only 32-bit wide:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/ftell-ftelli64?view=msvc-170

So, they should probably be calling `_fseeki64` and `_ftelli64` on Windows regardless of whether `off_t` is 32-bit or 64-bit.

The following patch to upstream gnulib fixes that for me:

diff --git a/lib/fseeko.c b/lib/fseeko.c
index 2c3b053a3b..30f8f70afe 100644
--- a/lib/fseeko.c
+++ b/lib/fseeko.c
@@ -31,7 +31,7 @@ fseeko (FILE *fp, off_t offset, int whence)
 # undef fseek
 # define fseeko fseek
 #endif
-#if _GL_WINDOWS_64_BIT_OFF_T
+#if _WIN32
 # undef fseeko
 # if HAVE__FSEEKI64 && HAVE_DECL__FSEEKI64 /* msvc, mingw since msvcrt8.0, mingw64 */
 #  define fseeko _fseeki64
diff --git a/lib/ftello.c b/lib/ftello.c
index 88247bca8e..2f83c61c0e 100644
--- a/lib/ftello.c
+++ b/lib/ftello.c
@@ -34,7 +34,7 @@ ftello (FILE *fp)
 # undef ftell
 # define ftello ftell
 #endif
-#if _GL_WINDOWS_64_BIT_OFF_T
+#if _WIN32
 # undef ftello
 # if HAVE__FTELLI64 /* msvc, mingw64 */
 #  define ftello _ftelli64


It might make sense to also ask about that on the gnulib mailing list.

Markus Mützel <mmuetzel>
Group administrator
Thu 07 Nov 2024 03:02:31 AM UTC, comment #6: 

@markus, not sure if you have any insight on this windows 'feature'?

Nicholas Jankowski <nrjank>
Group Member
Thu 07 Nov 2024 12:29:20 AM UTC, comment #5: 

I confirm the problem on Win11 with 9.2.1 using
"Fedora-Workstation-Live-x86_64-41-1.4.iso" as an example
(this is just a 2+GB file I had at hand).
It also works as expected on linux:

octave:1> fn = "Fedora-Workstation-Live-x86_64-41-1.4.iso"
fn = Fedora-Workstation-Live-x86_64-41-1.4.iso
octave:2>  ls ("-lh", fn)
-rw-r--r-- 1 dima dima 2.3G Oct 29 16:02 Fedora-Workstation-Live-x86_64-41-1.4.iso
octave:3> fid = fopen(fn)
fid = 19
octave:4> ftell(fid)
ans = 0
octave:5> [dseq, cnt] = fread(fid, 320, "uint8");
octave:6> ftell(fid)
ans = 320
octave:7> fseek(fid, 0, "bof")
ans = 0
octave:8> ftell(fid)
ans = 0


So it appears to be one one of those Windows thing.
May be somebody can add CC to markus <mmuetzel>

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Wed 06 Nov 2024 11:21:59 PM UTC, comment #4: 

Sure, I can do that, but let me show you this first.  Here is a directory listing of all the data files in my working directory, including the file in my original question:

>> ls -l -S *.dat -r

-rw-r--r-- 1 mmccully None    6400000 Aug 14 16:12 'Data_Md1Seg256Ch1Rng'$'\302\261''1000mVSR4G_1_2.dat'
-rw-r--r-- 1 mmccully None    6400000 Aug 14 16:11 'Data_Md1Seg256Ch1Rng'$'\302\261''1000mVSR4G_1_1.dat'
-rw-r--r-- 1 mmccully None   25690112 Aug  9 16:37 'Data_256Seg'$'\302\261''200mVRng4GSampRate_1_1.dat'
-rw-r--r-- 1 mmccully None  244056064 Aug  5 13:22 'Data_256Seg'$'\302\261''50mVRng4GSampRate_1_1.dat'
-rw-r--r-- 1 mmccully None 1785462784 Aug  6 20:16 'Data_256Seg'$'\302\261''50mVRng4GSampRate_1_2.dat'
-rw-r--r-- 1 mmccully None 2299265024 Aug  8 16:30 'Data_256Seg'$'\302\261''1000mVRng4GSampRate_1_1.dat'

>>


The files are listed by increasing order of size, as you can see.  The two reasons for the listing are:
(1) I processed all of the other files without any fseek() or ftell() errors, and
(2) The largest file, the one in my original question, is the only one that has a size that translates into a negative 32-bit number.

My apologies for not clarifying before that I didn't have trouble with files with a size <= 0x7FFFFFFF.

At any rate, I can send a portion of the file you asked about, and I can truncate it to any size you want.

Thanks...

MikeMcC <mmccully>
Tue 05 Nov 2024 06:55:11 PM UTC, comment #3: 

Thanks, so that doesn't make a difference.

Well, next question is if the file encoding could be interfering. But I'm unfamiliar with that part of Octave's code.

Would it be possible to upload (a first part, say a good part beyond the 640 char limit that you invoked) of that file 'Data_256Seg±1000mVRng4GSampRate_1_1.dat' so that we can try ourselves?

BTW, a hint:
If you enter the command
 format compact
in the terminal Octave doesn't echo empty lines in its output. Makes for more easy reading here (less scrolling needed)
I have that command in my .octaverc

Philip Nienhuis <philipnienhuis>
Group Member
Mon 04 Nov 2024 11:32:51 PM UTC, comment #2: 

OK, here are all the same commands from the first post, except that the fseek() calls were modified as requested.

>> fileName

fileName = Data_256Seg±1000mVRng4GSampRate_1_1.dat

>> ls -l Data_256Seg±1000mVRng4GSampRate_1_1.dat

-rw-r--r-- 1 mmccully None 2299265024 Aug  8 16:30 'Data_256Seg'$'\302\261''1000mVRng4GSampRate_1_1.dat'

>> fileID = fopen(fileName)

fileID = 3

>> ftell(fileID)

ans = 0

>> [dataSeg, count] = fread(fileID, 320, 'uint8');
>> count

count = 320

>> ftell(fileID)

ans = 320

>> fseek(fileID, 0, "bof")

ans = -1

>> ftell(fileID)

ans = 320

>> fseek(fileID, 0, "eof")

ans = -1

>> ftell(fileID)

ans = 320

>> [dataSeg, count] = fread(fileID, 320, 'uint8');
>> ftell(fileID)

ans = 640

>> fclose(fileID)

ans = 0

>>

MikeMcC <mmccully>
Mon 04 Nov 2024 09:18:56 PM UTC, comment #1: 

Can you try with "bof" and "eof" rather than SEEK_SET and SEEK_END and report back, please?

Philip Nienhuis <philipnienhuis>
Group Member
Sat 02 Nov 2024 10:56:24 PM UTC, original submission:  

Hello,

As background, I recently downloaded Octave 9.2.0 and am running it under the latest update of Win11.  The 'About Octave' message box for my version is attached as a JPEG in order to give specific info about Octave.

I'm working with a large file under Windows 11, larger than 2GB, and the fseek function returns -1 when I try to do any kind of file seek.  That is, it doesn't matter if I use SEEK_SET, SEEK_CUR or SEEK_END.  I was originally trying to do SEEK_END to get the file size.

The ftell function works right, but apparently not after the file position turns into a 32-bit negative number.

I looked at bug #57644 before submitting this, and it says this bug was found and fixed before, but I seem to be having trouble, so here is my submission.

Below is a short example of some commands I entered into the Octave Command Window.  What I did was cut the text from the command window and paste it here.
The first line shows the name of the file with which I am working, the second line lists the directory info including the file size, and in the commands that follow I open the file, read from it, call ftell and fseek to show their results, and close the file.  Here are the commands.

>>fileName

fileName = Data_256Seg±1000mVRng4GSampRate_1_1.dat

>> ls -l Data_256Seg±1000mVRng4GSampRate_1_1.dat

-rw-r--r-- 1 mmccully None 2299265024 Aug  8 16:30 'Data_256Seg'$'\302\261''1000mVRng4GSampRate_1_1.dat'

>>fileID = fopen(fileName)

fileID = 3

>>ftell(fileID)

ans = 0

>>[dataSeg, count] = fread(fileID, 320, 'uint8');
>> count

count = 320

>> ftell(fileID)

ans = 320

>> fseek(fileID, 0, SEEK_SET)

ans = -1

>> ftell(fileID)

ans = 320

>> fseek(fileID, 0, SEEK_END)

ans = -1

>> ftell(fileID)

ans = 320

>> [dataSeg, count] = fread(fileID, 320, 'uint8');
>> ftell(fileID)

ans = 640

>> fclose(fileID)

ans = 0

>>


Any light anyone can shed on this will be a big help.  Thanks.

MikeMcC <mmccully>

 

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

Attach Files:
   
   
Comment:
   

Attached Files
file #56612:  octave-fseeko.diff added by eggert (3KiB - text/x-patch - incomplete patch to use fseeko instead of fseek internally)
file #56590:  AboutOctave.jpg added by mmccully (51KiB - image/jpeg)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by eggert (Posted a comment)
  • -email is unavailable- added by mmuetzel (Posted a comment)
  • -email is unavailable- added by nrjank (Posted a comment)
  • -email is unavailable- added by nrjank
  • -email is unavailable- added by dasergatskov (Posted a comment)
  • -email is unavailable- added by mmccully (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 8 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2024-11-14 mmuetzel StatusConfirmed Ready For Test
    2024-11-12 eggert Attached File- Added octave-fseeko.diff, #56612
    2024-11-11 mmuetzel Planned ReleaseNone 10.1.0 (current default)
    2024-11-07 nrjank Summaryfseek and ftell functions don't always work correctly on Win11 fseek and ftell functions don't always work correctly on Win11 with filesizes >2GB
    2024-11-07 nrjank StatusNeed Info Confirmed
    2024-11-07 nrjank Carbon-Copy- Added mmuetzel
    2024-11-04 philipnienhuis StatusNone Need Info
    2024-11-02 mmccully Attached File- Added AboutOctave.jpg, #56590

    Back to the top

    Powered by Savane 3.14-f13d.
    Corresponding source code