| #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 |