Fix errors when over-reading a "large" amount from FileGroups on
authorCarl Hetherington <cth@carlh.net>
Tue, 6 Oct 2020 23:02:47 +0000 (01:02 +0200)
committerCarl Hetherington <cth@carlh.net>
Tue, 13 Oct 2020 16:51:11 +0000 (18:51 +0200)
Windows.  I haven't been able to find any conclusive explanation for
why this stuff happens;

https://stackoverflow.com/questions/7241168/safe-maximum-number-of-records-read-by-fread

is one possible lead.

src/lib/file_group.cc
src/lib/file_group.h

index 3e8a7b79c43177a8d775889ab91d08855bb0e77e..9863a21cbd37617c5f69fa14be7aae7bb5b55dc5 100644 (file)
@@ -37,6 +37,7 @@ using std::cout;
 FileGroup::FileGroup ()
        : _current_path (0)
        , _current_file (0)
 FileGroup::FileGroup ()
        : _current_path (0)
        , _current_file (0)
+       , _current_size (0)
 {
 
 }
 {
 
 }
@@ -45,6 +46,7 @@ FileGroup::FileGroup ()
 FileGroup::FileGroup (boost::filesystem::path p)
        : _current_path (0)
        , _current_file (0)
 FileGroup::FileGroup (boost::filesystem::path p)
        : _current_path (0)
        , _current_file (0)
+       , _current_size (0)
 {
        _paths.push_back (p);
        ensure_open_path (0);
 {
        _paths.push_back (p);
        ensure_open_path (0);
@@ -95,6 +97,7 @@ FileGroup::ensure_open_path (size_t p) const
        if (_current_file == 0) {
                throw OpenFileError (_paths[_current_path], errno, OpenFileError::READ);
        }
        if (_current_file == 0) {
                throw OpenFileError (_paths[_current_path], errno, OpenFileError::READ);
        }
+       _current_size = boost::filesystem::file_size (_paths[_current_path]);
 }
 
 int64_t
 }
 
 int64_t
@@ -155,7 +158,15 @@ FileGroup::read (uint8_t* buffer, int amount) const
 {
        int read = 0;
        while (true) {
 {
        int read = 0;
        while (true) {
-               int const this_time = fread (buffer + read, 1, amount - read, _current_file);
+               int64_t to_read = amount - read;
+#ifdef DCPOMATIC_WINDOWS
+               /* If we over-read from the file by too much on Windows we get a errno=22 rather than an feof condition,
+                * for unknown reasons.  So if we're going to over-read, we need to do it by a little bit, so that feof
+                * still gets triggered but there is no errno=22.
+                */
+               to_read = std::min(to_read, static_cast<int64_t>(_current_size - _ftelli64(_current_file) + 1));
+#endif
+               int const this_time = fread (buffer + read, 1, to_read, _current_file);
                read += this_time;
                if (read == amount) {
                        /* Done */
                read += this_time;
                if (read == amount) {
                        /* Done */
index 800d9a059ec949e19497f2aca0256ab7bd9feeb2..21499f5634483feac8f589ac79c797160975502e 100644 (file)
@@ -52,6 +52,7 @@ private:
        /** Index of path that we are currently reading from */
        mutable size_t _current_path;
        mutable FILE* _current_file;
        /** Index of path that we are currently reading from */
        mutable size_t _current_path;
        mutable FILE* _current_file;
+       mutable size_t _current_size;
 };
 
 #endif
 };
 
 #endif