diff --git a/hecl/include/hecl/ClientProcess.hpp b/hecl/include/hecl/ClientProcess.hpp index eb9320b46..c55176caa 100644 --- a/hecl/include/hecl/ClientProcess.hpp +++ b/hecl/include/hecl/ClientProcess.hpp @@ -19,6 +19,7 @@ class ClientProcess public: struct Transaction { + ClientProcess& m_parent; enum class Type { Buffer, @@ -26,7 +27,7 @@ public: } m_type; bool m_complete = false; virtual void run()=0; - Transaction(Type tp) : m_type(tp) {} + Transaction(ClientProcess& parent, Type tp) : m_parent(parent), m_type(tp) {} }; struct BufferTransaction : Transaction { @@ -35,17 +36,19 @@ public: size_t m_maxLen; size_t m_offset; void run(); - BufferTransaction(const ProjectPath& path, void* target, size_t maxLen, size_t offset) - : Transaction(Type::Buffer), m_path(path), m_targetBuf(target), m_maxLen(maxLen), m_offset(offset) {} + BufferTransaction(ClientProcess& parent, const ProjectPath& path, + void* target, size_t maxLen, size_t offset) + : Transaction(parent, Type::Buffer), + m_path(path), m_targetBuf(target), + m_maxLen(maxLen), m_offset(offset) {} }; struct CookTransaction : Transaction { ProjectPath m_path; - bool m_verbose; int m_returnVal = 0; void run(); - CookTransaction(const ProjectPath& path, bool verbose) - : Transaction(Type::Cook), m_path(path), m_verbose(verbose) {} + CookTransaction(ClientProcess& parent, const ProjectPath& path) + : Transaction(parent, Type::Cook), m_path(path) {} }; private: std::list> m_pendingQueue; @@ -64,9 +67,10 @@ private: public: ClientProcess(int verbosityLevel=1); ~ClientProcess() {shutdown();} - void addBufferTransaction(const hecl::ProjectPath& path, void* target, - size_t maxLen, size_t offset); - void addCookTransaction(const hecl::ProjectPath& path); + const BufferTransaction* addBufferTransaction(const hecl::ProjectPath& path, void* target, + size_t maxLen, size_t offset); + const CookTransaction* addCookTransaction(const hecl::ProjectPath& path); + int syncCook(const hecl::ProjectPath& path); void swapCompletedQueue(std::list>& queue); void shutdown(); }; diff --git a/hecl/lib/ClientProcess.cpp b/hecl/lib/ClientProcess.cpp index cdaa081d7..486516a2c 100644 --- a/hecl/lib/ClientProcess.cpp +++ b/hecl/lib/ClientProcess.cpp @@ -14,7 +14,8 @@ static logvisor::Module Log("hecl::ClientProcess"); static bool ExecProcessAndWait(bool verbose, const SystemChar* exePath, - const SystemChar* args[]) + const SystemChar* args[], + int& returnCode) { #if _WIN32 std::wstring cmdLine; @@ -53,6 +54,7 @@ static bool ExecProcessAndWait(bool verbose, WaitForSingleObject(pinfo.hProcess, INFINITE); DWORD exitCode; GetExitCodeProcess(pinfo.hProcess, &exitCode); + returnCode = exitCode; CloseHandle(pinfo.hProcess); if (exitCode == 0) @@ -81,10 +83,7 @@ static bool ExecProcessAndWait(bool verbose, if (execvp(exePath, (char*const*)assembleArgs.data()) < 0) { - if (errno == ENOENT) - return false; - else - Log.report(logvisor::Fatal, _S("error execing '%s': %s"), exePath, strerror(errno)); + Log.report(logvisor::Fatal, _S("error execing '%s': %s"), exePath, strerror(errno)); } exit(1); @@ -95,8 +94,13 @@ static bool ExecProcessAndWait(bool verbose, Log.report(logvisor::Fatal, "unable to wait for hecl process to complete: %s", strerror(errno)); if (WIFEXITED(exitStatus)) + { + returnCode = WEXITSTATUS(exitStatus); if (WEXITSTATUS(exitStatus) == 0) + { return true; + } + } return false; @@ -126,14 +130,13 @@ void ClientProcess::BufferTransaction::run() if (m_offset) r.seek(m_offset, athena::Begin); r.readBytesToBuf(m_targetBuf, m_maxLen); + m_complete = true; } void ClientProcess::CookTransaction::run() { - const SystemChar* args[] = {_S("cook"), m_path.getAbsolutePath().c_str()}; - if (!ExecProcessAndWait(m_verbose, _S("hecl"), args)) - Log.report(logvisor::Fatal, _S("unable to background-cook '%s'"), - m_path.getAbsolutePath().c_str()); + m_returnVal = m_parent.syncCook(m_path); + m_complete = true; } ClientProcess::Worker::Worker(ClientProcess& proc) @@ -169,19 +172,35 @@ ClientProcess::ClientProcess(int verbosityLevel) m_workers.emplace_back(*this); } -void ClientProcess::addBufferTransaction(const ProjectPath& path, void* target, - size_t maxLen, size_t offset) +const ClientProcess::BufferTransaction* +ClientProcess::addBufferTransaction(const ProjectPath& path, void* target, + size_t maxLen, size_t offset) { std::unique_lock lk(m_mutex); - m_pendingQueue.emplace_back(new BufferTransaction(path, target, maxLen, offset)); + BufferTransaction* ret = new BufferTransaction(*this, path, target, maxLen, offset); + m_pendingQueue.emplace_back(ret); m_cv.notify_one(); + return ret; } -void ClientProcess::addCookTransaction(const hecl::ProjectPath& path) +const ClientProcess::CookTransaction* +ClientProcess::addCookTransaction(const hecl::ProjectPath& path) { std::unique_lock lk(m_mutex); - m_pendingQueue.emplace_back(new CookTransaction(path, m_verbosity != 0)); + CookTransaction* ret = new CookTransaction(*this, path); + m_pendingQueue.emplace_back(ret); m_cv.notify_one(); + return ret; +} + +int ClientProcess::syncCook(const hecl::ProjectPath& path) +{ + const SystemChar* args[] = {_S("cook"), path.getAbsolutePath().c_str()}; + int returnCode; + if (!ExecProcessAndWait(m_verbosity != 0, _S("hecl"), args, returnCode)) + Log.report(logvisor::Fatal, _S("unable to background-cook '%s'"), + path.getAbsolutePath().c_str()); + return returnCode; } void ClientProcess::swapCompletedQueue(std::list>& queue)