Skip to content

Commit

Permalink
fixed libtiff handling of file IO by providing the proper sharing fla…
Browse files Browse the repository at this point in the history
…g so the file can be deleted while open for reading
  • Loading branch information
debaetsd committed Jan 6, 2021
1 parent 67551c7 commit ee50a3a
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/libOpenImageIO/imagebuf_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ test_write_over()
OIIO_CHECK_ASSERT(pixel[0] == 0 && pixel[1] == 1 && pixel[2] == 0);

// Replace the green image with red, under the nose of the ImageBuf.
Filesystem::remove("tmp-green.tif");
OIIO_CHECK_ASSERT(Filesystem::remove("tmp-green.tif") == true);
Filesystem::copy("tmp-red.tif", "tmp-green.tif");

// Read the image again -- different ImageBuf.
Expand Down
22 changes: 22 additions & 0 deletions src/tiff.imageio/tiffinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,10 @@ TIFFInput::open(const std::string& name, ImageSpec& newspec,
return open(name, newspec);
}

#define WIN_SHARE_DELETE_WORKAROUND 1
#if defined(_WIN32) && WIN_SHARE_DELETE_WORKAROUND
#include <fcntl.h>
#endif


bool
Expand Down Expand Up @@ -661,7 +665,25 @@ TIFFInput::seek_subimage(int subimage, int miplevel)
if (!m_tif) {
#ifdef _WIN32
std::wstring wfilename = Strutil::utf8_to_utf16(m_filename);

// workaround for libtiff not passing FILE_SHARE_DELETE attribute
// Without this flag, a process cannot delete files that it has opened (for reading).
#if !WIN_SHARE_DELETE_WORKAROUND
m_tif = TIFFOpenW(wfilename.c_str(), "rm");
#else
int m = O_RDONLY; /*_TIFFgetMode(mode, module);*/
int dwMode = OPEN_EXISTING /*case O_RDONLY: dwMode = OPEN_EXISTING; break;*/;
HANDLE fd = CreateFileW(wfilename.c_str(),
(m == O_RDONLY) ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE , NULL, dwMode,
(m == O_RDONLY) ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL,
NULL);
if (fd != INVALID_HANDLE_VALUE)
{
m_tif = TIFFFdOpen((int)fd, "<tiff_oiio_todo>","rm"); /* FIXME: WIN64 cast from pointer to int warning */
if (!m_tif) CloseHandle(fd);
}
#endif
#else
m_tif = TIFFOpen(m_filename.c_str(), "rm");
#endif
Expand Down

1 comment on commit ee50a3a

@lgritz
Copy link

@lgritz lgritz commented on ee50a3a Jan 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should suggest this to libtiff, but not put all this code here that is completely specific to Windows.

Our use of remove is problematic -- because we previously read the file with an ImageBuf, it's possible that it's backed by ImageCache which is holding an open ImageInput for that file. It's an unusual and ill-advised to try to remove a file that your own process is using. The right solution is to fix the test, by making sure to tell the cache to close the file before removing it. Let me test a quick fix and if it works I'll submit a PR.

Please sign in to comment.