Make sure TempFilePath always generate unique file path

Previously it is possible that the same file path is generated when
the function is called consecutively in the same thread.

The problem can be re-produced in Windows. Does not seem to be
re-producible in Linux and Mac.

Fixes #448, #449.

Change-Id: Ia0163492e3494eba00f56f4d356aa1010b9660cc
This commit is contained in:
KongQun Yang 2018-08-06 16:11:57 -07:00
parent d932153dd7
commit b4e827e01b
2 changed files with 31 additions and 5 deletions

View File

@ -19,11 +19,19 @@ namespace shaka {
namespace { namespace {
// Create a temp file name using process id, thread id and current time. // Create a temp file name using process id, thread id and current time.
std::string TempFileName() { std::string TempFileName() {
const int32_t pid = static_cast<int32_t>(base::GetCurrentProcId()); const int32_t process_id = static_cast<int32_t>(base::GetCurrentProcId());
const int32_t tid = static_cast<int32_t>(base::PlatformThread::CurrentId()); const int32_t thread_id =
static_cast<int32_t>(base::PlatformThread::CurrentId());
// We may need two or more temporary files in the same thread. There might be
// name collision if they are requested around the same time, e.g. called
// consecutively. Use a thread_local instance to avoid that.
static thread_local int32_t instance_id = 0;
++instance_id;
const int64_t current_time = base::Time::Now().ToInternalValue(); const int64_t current_time = base::Time::Now().ToInternalValue();
return base::StringPrintf("packager-tempfile-%x-%x-%" PRIx64, pid, tid, return base::StringPrintf("packager-tempfile-%x-%x-%x-%" PRIx64, process_id,
current_time); thread_id, instance_id, current_time);
} }
} // namespace } // namespace

View File

@ -8,15 +8,33 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "packager/base/logging.h"
namespace shaka { namespace shaka {
TEST(FileUtilTest, Basic) { TEST(FileUtilTest, TempFilePathInDesignatedDirectory) {
std::string temp_file_path; std::string temp_file_path;
EXPECT_TRUE(TempFilePath("test", &temp_file_path)); EXPECT_TRUE(TempFilePath("test", &temp_file_path));
EXPECT_EQ(temp_file_path.find("test"), 0u); EXPECT_EQ(temp_file_path.find("test"), 0u);
LOG(INFO) << "temp file path: " << temp_file_path;
}
TEST(FileUtilTest, TempFilePathInSystemTempDirectory) {
std::string temp_file_path;
EXPECT_TRUE(TempFilePath("", &temp_file_path)); EXPECT_TRUE(TempFilePath("", &temp_file_path));
// temp_file_path should be created in a system specific temp directory. // temp_file_path should be created in a system specific temp directory.
LOG(INFO) << "temp file path: " << temp_file_path;
}
TEST(FileUtilTest, TempFilePathCalledTwice) {
const char kTempDir[] = "/test/";
std::string temp_file_path1;
std::string temp_file_path2;
ASSERT_TRUE(TempFilePath(kTempDir, &temp_file_path1));
ASSERT_TRUE(TempFilePath(kTempDir, &temp_file_path2));
ASSERT_NE(temp_file_path1, temp_file_path2);
LOG(INFO) << "temp file path1: " << temp_file_path1;
LOG(INFO) << "temp file path2: " << temp_file_path2;
} }
} // namespace shaka } // namespace shaka