|  | #pragma once | 
|  |  | 
|  | #ifndef _WIN32 | 
|  | #include <signal.h> | 
|  | #include <sys/wait.h> | 
|  | #include <unistd.h> | 
|  | #endif | 
|  |  | 
|  | #include <sys/types.h> | 
|  | #include <cstring> | 
|  |  | 
|  | #include <condition_variable> | 
|  | #include <mutex> | 
|  | #include <string> | 
|  | #include <system_error> | 
|  | #include <vector> | 
|  |  | 
|  | namespace c10d { | 
|  | namespace test { | 
|  |  | 
|  | class Semaphore { | 
|  | public: | 
|  | void post(int n = 1) { | 
|  | std::unique_lock<std::mutex> lock(m_); | 
|  | n_ += n; | 
|  | cv_.notify_all(); | 
|  | } | 
|  |  | 
|  | void wait(int n = 1) { | 
|  | std::unique_lock<std::mutex> lock(m_); | 
|  | while (n_ < n) { | 
|  | cv_.wait(lock); | 
|  | } | 
|  | n_ -= n; | 
|  | } | 
|  |  | 
|  | protected: | 
|  | int n_ = 0; | 
|  | std::mutex m_; | 
|  | std::condition_variable cv_; | 
|  | }; | 
|  |  | 
|  | #ifdef _WIN32 | 
|  | std::string autoGenerateTmpFilePath() { | 
|  | char tmp[L_tmpnam_s]; | 
|  | errno_t err; | 
|  | err = tmpnam_s(tmp, L_tmpnam_s); | 
|  | if (err != 0) | 
|  | { | 
|  | throw std::system_error(errno, std::system_category()); | 
|  | } | 
|  | return std::string(tmp); | 
|  | } | 
|  |  | 
|  | std::string tmppath() { | 
|  | const char* tmpfile = getenv("TMPFILE"); | 
|  | if (tmpfile) { | 
|  | return std::string(tmpfile); | 
|  | } | 
|  | else { | 
|  | return autoGenerateTmpFilePath(); | 
|  | } | 
|  | } | 
|  | #else | 
|  | std::string tmppath() { | 
|  | // TMPFILE is for manual test execution during which the user will specify | 
|  | // the full temp file path using the environmental variable TMPFILE | 
|  | const char* tmpfile = getenv("TMPFILE"); | 
|  | if (tmpfile) { | 
|  | return std::string(tmpfile); | 
|  | } | 
|  |  | 
|  | const char* tmpdir = getenv("TMPDIR"); | 
|  | if (tmpdir == nullptr) { | 
|  | tmpdir = "/tmp"; | 
|  | } | 
|  |  | 
|  | // Create template | 
|  | std::vector<char> tmp(256); | 
|  | auto len = snprintf(tmp.data(), tmp.size(), "%s/testXXXXXX", tmpdir); | 
|  | tmp.resize(len); | 
|  |  | 
|  | // Create temporary file | 
|  | auto fd = mkstemp(&tmp[0]); | 
|  | if (fd == -1) { | 
|  | throw std::system_error(errno, std::system_category()); | 
|  | } | 
|  | close(fd); | 
|  | return std::string(tmp.data(), tmp.size()); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | bool isTSANEnabled() { | 
|  | auto s = std::getenv("PYTORCH_TEST_WITH_TSAN"); | 
|  | return s && strcmp(s, "1") == 0; | 
|  | } | 
|  | struct TemporaryFile { | 
|  | std::string path; | 
|  |  | 
|  | TemporaryFile() { | 
|  | path = tmppath(); | 
|  | } | 
|  |  | 
|  | ~TemporaryFile() { | 
|  | unlink(path.c_str()); | 
|  | } | 
|  | }; | 
|  |  | 
|  | #ifndef _WIN32 | 
|  | struct Fork { | 
|  | pid_t pid; | 
|  |  | 
|  | Fork() { | 
|  | pid = fork(); | 
|  | if (pid < 0) { | 
|  | throw std::system_error(errno, std::system_category(), "fork"); | 
|  | } | 
|  | } | 
|  |  | 
|  | ~Fork() { | 
|  | if (pid > 0) { | 
|  | kill(pid, SIGKILL); | 
|  | waitpid(pid, nullptr, 0); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool isChild() { | 
|  | return pid == 0; | 
|  | } | 
|  | }; | 
|  | #endif | 
|  |  | 
|  | } // namespace test | 
|  | } // namespace c10d |