2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-08 21:07:42 +00:00

Decided against child cook process

This commit is contained in:
Jack Andersen
2016-03-28 12:39:18 -10:00
parent 3822f001a8
commit c06cc88441
7 changed files with 76 additions and 159 deletions

View File

@@ -1,6 +1,7 @@
#include "hecl/ClientProcess.hpp"
#include "hecl/Database.hpp"
#include "athena/FileReader.hpp"
#include "BlenderConnection.hpp"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
@@ -13,115 +14,6 @@ namespace hecl
{
static logvisor::Module Log("hecl::ClientProcess");
static bool ExecProcessAndWait(bool verbose,
const SystemChar* exePath,
const SystemChar* workDir,
const SystemChar* args[],
int& returnCode)
{
#if _WIN32
std::wstring cmdLine;
for (const SystemChar** it=args ; *it ; ++it)
{
if (it != args)
cmdLine.append(L' ');
cmdLine.append(*it);
}
STARTUPINFO sinfo = {sizeof(STARTUPINFO)};
HANDLE nulHandle = NULL;
if (!verbose)
{
SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
nulHandle = CreateFileW(L"nul", GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &sattrs,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
sinfo.hStdError = nulHandle;
sinfo.hStdOutput = nulHandle;
sinfo.dwFlags = STARTF_USESTDHANDLES;
}
PROCESS_INFORMATION pinfo;
if (!CreateProcessW(exePath, cmdLine.c_str(), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, workDir, &sinfo, &pinfo))
{
LPWSTR messageBuffer = nullptr;
size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, NULL);
Log.report(logvisor::Fatal, L"error launching '%s': %s", exePath, messageBuffer);
}
if (nulHandle)
CloseHandle(nulHandle);
CloseHandle(pinfo.hThread);
WaitForSingleObject(pinfo.hProcess, INFINITE);
DWORD exitCode;
GetExitCodeProcess(pinfo.hProcess, &exitCode);
returnCode = exitCode;
CloseHandle(pinfo.hProcess);
if (exitCode == 0)
return true;
return false;
#else
/* Assemble command args */
std::vector<const SystemChar*> assembleArgs;
size_t argCount = 0;
for (const SystemChar** it=args ; *it ; ++it) ++argCount;
assembleArgs.reserve(argCount+2);
assembleArgs.push_back(exePath);
for (const SystemChar** it=args ; *it ; ++it) assembleArgs.push_back(*it);
assembleArgs.push_back(nullptr);
if (verbose)
{
printf("cd %s\n", workDir);
for (const SystemChar* arg : assembleArgs)
if (arg)
printf("%s ", arg);
printf("\n");
fflush(stdout);
}
pid_t pid = fork();
if (!pid)
{
chdir(workDir);
if (!verbose)
{
int devNull = open("/dev/null", O_WRONLY);
dup2(devNull, STDOUT_FILENO);
dup2(devNull, STDERR_FILENO);
}
if (execvp(exePath, (char*const*)assembleArgs.data()) < 0)
{
Log.report(logvisor::Fatal, _S("error execing '%s': %s"), exePath, strerror(errno));
}
exit(1);
}
int exitStatus;
if (waitpid(pid, &exitStatus, 0) < 0)
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;
#endif
}
static int GetCPUCount()
{
#if _WIN32
@@ -133,7 +25,7 @@ static int GetCPUCount()
#endif
}
void ClientProcess::BufferTransaction::run()
void ClientProcess::BufferTransaction::run(BlenderToken& btok)
{
athena::io::FileReader r(m_path.getAbsolutePath(), 32 * 1024, false);
if (r.hasError())
@@ -148,9 +40,9 @@ void ClientProcess::BufferTransaction::run()
m_complete = true;
}
void ClientProcess::CookTransaction::run()
void ClientProcess::CookTransaction::run(BlenderToken& btok)
{
m_returnVal = m_parent.syncCook(m_path);
m_returnResult = m_parent.syncCook(m_path, m_dataSpec, btok);
m_complete = true;
}
@@ -170,7 +62,7 @@ void ClientProcess::Worker::proc()
std::unique_ptr<Transaction> trans = std::move(m_proc.m_pendingQueue.front());
m_proc.m_pendingQueue.pop_front();
lk.unlock();
trans->run();
trans->run(m_blendTok);
lk.lock();
m_proc.m_completedQueue.push_back(std::move(trans));
}
@@ -199,30 +91,28 @@ ClientProcess::addBufferTransaction(const ProjectPath& path, void* target,
}
const ClientProcess::CookTransaction*
ClientProcess::addCookTransaction(const hecl::ProjectPath& path)
ClientProcess::addCookTransaction(const hecl::ProjectPath& path, Database::IDataSpec* spec)
{
std::unique_lock<std::mutex> lk(m_mutex);
CookTransaction* ret = new CookTransaction(*this, path);
CookTransaction* ret = new CookTransaction(*this, path, spec);
m_pendingQueue.emplace_back(ret);
m_cv.notify_one();
return ret;
}
int ClientProcess::syncCook(const hecl::ProjectPath& path)
bool ClientProcess::syncCook(const hecl::ProjectPath& path, Database::IDataSpec* spec, BlenderToken& btok)
{
const SystemChar* workDir = path.getProject().getProjectWorkingPath().getAbsolutePath().c_str();
const SystemChar* args[] = {_S("cook"), path.getAbsolutePath().c_str(), nullptr};
int returnCode;
const SystemChar* heclOverride = hecl::GetEnv(_S("HECL_BIN"));
if (heclOverride)
if (spec->canCook(path, btok))
{
if (ExecProcessAndWait(m_verbosity != 0, heclOverride, workDir, args, returnCode))
return returnCode;
const Database::DataSpecEntry* specEnt = spec->overrideDataSpec(path, spec->getDataSpecEntry(), btok);
if (specEnt)
{
hecl::ProjectPath cooked = path.getCookedPath(*specEnt);
spec->doCook(path, cooked, false, btok, [](const SystemChar*) {});
return true;
}
}
if (!ExecProcessAndWait(m_verbosity != 0, _S("hecl"), workDir, args, returnCode))
Log.report(logvisor::Fatal, _S("unable to background-cook '%s'"),
path.getAbsolutePath().c_str());
return returnCode;
return false;
}
void ClientProcess::swapCompletedQueue(std::list<std::unique_ptr<Transaction>>& queue)