Add support for closing a TemporaryFile early
authorChristopher Dykes <cdykes@fb.com>
Thu, 13 Jul 2017 18:50:36 +0000 (11:50 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 13 Jul 2017 18:57:20 +0000 (11:57 -0700)
Summary:
The file itself will still get removed when `TemporaryFile` is destroyed, but closing it before then allows it to be read when on Windows, because `TemporaryFile` opens the temporary file with `O_EXCL`, so Windows denies read access of the file to everything else.
This is needed to fix one of the AsyncFileWriter tests on Windows.

Reviewed By: simpkins

Differential Revision: D5307719

fbshipit-source-id: bd65962cc3d34f382cc7b0b55dbf2659ed5ebfce

folly/experimental/TestUtil.cpp
folly/experimental/TestUtil.h
folly/experimental/test/TestUtilTest.cpp

index d0f39b940b4d845c3b66f50df82a7444f18c0c66..cbaa3246c43ed859294894d03d12de91ebed70c1 100644 (file)
@@ -74,6 +74,13 @@ TemporaryFile::TemporaryFile(StringPiece namePrefix,
   }
 }
 
+void TemporaryFile::close() {
+  if (::close(fd_) == -1) {
+    PLOG(ERROR) << "close failed";
+  }
+  fd_ = -1;
+}
+
 const fs::path& TemporaryFile::path() const {
   CHECK(scope_ != Scope::UNLINK_IMMEDIATELY);
   DCHECK(!path_.empty());
@@ -82,7 +89,7 @@ const fs::path& TemporaryFile::path() const {
 
 TemporaryFile::~TemporaryFile() {
   if (fd_ != -1 && closeOnDestruction_) {
-    if (close(fd_) == -1) {
+    if (::close(fd_) == -1) {
       PLOG(ERROR) << "close failed";
     }
   }
index cc110feb91dd9706efd80028f6767a074bf8a11e..2460b84bc40d1dfd051d76476f2aecd9d52f1743 100644 (file)
@@ -54,6 +54,7 @@ class TemporaryFile {
   TemporaryFile(TemporaryFile&&) = default;
   TemporaryFile& operator=(TemporaryFile&&) = default;
 
+  void close();
   int fd() const { return fd_; }
   const fs::path& path() const;
 
index 32196eccdac83c9d320612faa5db1065696f8321..72b9ccbf201acfeceedce393f49d61607ddb94b8 100644 (file)
@@ -53,6 +53,19 @@ TEST(TemporaryFile, Simple) {
   });
 }
 
+TEST(TemporaryFile, EarlyClose) {
+  fs::path p;
+  {
+    TemporaryFile f;
+    p = f.path();
+    EXPECT_TRUE(fs::exists(p));
+    f.close();
+    EXPECT_EQ(-1, f.fd());
+    EXPECT_TRUE(fs::exists(p));
+  }
+  EXPECT_FALSE(fs::exists(p));
+}
+
 TEST(TemporaryFile, Prefix) {
   TemporaryFile f("Foo");
   EXPECT_TRUE(f.path().is_absolute());