Skip to content

Commit

Permalink
OrcLib: CommandAgent: synchronize with child process creation
Browse files Browse the repository at this point in the history
Use CreateChildProcess, ResumeChildProcess and new notifications
CommandNotification::Created and CommandNotification::Started to
ensure WolfTask will handle correctly process creation even if
quickly terminated.
  • Loading branch information
fabienfl-orc committed Nov 15, 2023
1 parent e21f681 commit 617faba
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 11 deletions.
3 changes: 3 additions & 0 deletions src/OrcCommand/Command/WolfLauncher/WolfTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ HRESULT WolfTask::ApplyNotification(
m_executableSha1 = notification->GetExecutableSha1();
m_isSelfOrcExecutable = notification->IsSelfOrcExecutable();
m_orcTool = notification->GetOrcTool();

actions.push_back(CommandMessage::MakeStartMessage(
notification->GetKeyword(), static_cast<DWORD>(static_cast<DWORD64>(notification->GetProcessID()))));
}
break;
case CommandNotification::Started:
Expand Down
53 changes: 42 additions & 11 deletions src/OrcLib/CommandAgent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,42 @@ std::shared_ptr<CommandExecute> CommandAgent::PrepareCommandExecute(const std::s
return retval;
}

void CommandAgent::StartCommandExecute(const std::shared_ptr<CommandMessage>& message)
{
Concurrency::critical_section::scoped_lock s(m_cs);

std::shared_ptr<CommandExecute> command = nullptr;
for (const auto& runningCommand : m_RunningCommands)
{
if (runningCommand == nullptr)
{
continue;
}

if (runningCommand->ProcessID() == message->ProcessID())
{
command = runningCommand;
}
}

if (command == nullptr)
{
Log::Critical(L"Command '{}' resume rejected, command not found", message->Keyword());
return;
}

HRESULT hr = command->ResumeChildProcess();
if (FAILED(hr))
{
Log::Critical(L"Command '{}' resume failed [{}]", message->Keyword(), SystemError(hr));
TerminateProcess(command->ProcessHandle(), -1);
return;
}

Concurrency::send<CommandNotification::Notification>(
m_target, CommandNotification::NotifyStarted(command->GetKeyword(), command->ProcessID()));
}

typedef struct _CompletionBlock
{
CommandAgent* pAgent;
Expand Down Expand Up @@ -804,6 +840,7 @@ HRESULT CommandAgent::ExecuteNextCommand()
timer->start();
}

// Register a callback that will handle process termination (release semaphore, notify, etc...)
HANDLE hWaitObject = INVALID_HANDLE_VALUE;
CompletionBlock* pBlockPtr = (CompletionBlock*)Concurrency::Alloc(sizeof(CompletionBlock));
CompletionBlock* pBlock = new (pBlockPtr) CompletionBlock;
Expand Down Expand Up @@ -834,17 +871,6 @@ HRESULT CommandAgent::ExecuteNextCommand()
notification->SetProcessCommandLine(command->m_commandLine);

SendResult(notification);

hr = command->ResumeChildProcess();
if (FAILED(hr))
{
m_MaximumRunningSemaphore.Release();
command->CompleteExecution();
return S_OK;
}

Concurrency::send<CommandNotification::Notification>(
m_target, CommandNotification::NotifyStarted(command->GetKeyword(), command->ProcessID()));
}

return S_OK;
Expand Down Expand Up @@ -1230,6 +1256,11 @@ void CommandAgent::run()
}
}
break;
case CommandMessage::Start: {
Log::Debug(L"CommandAgent: Start command '{}'", request->Keyword());
StartCommandExecute(request);
}
break;
case CommandMessage::RefreshRunningList: {
Concurrency::critical_section::scoped_lock s(m_cs);
auto new_end = std::remove_if(
Expand Down
1 change: 1 addition & 0 deletions src/OrcLib/CommandAgent.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ class CommandAgent : public Concurrency::agent
std::shared_ptr<ProcessRedirect>
PrepareRedirection(const std::shared_ptr<CommandExecute>& cmd, const CommandParameter& output);
std::shared_ptr<CommandExecute> PrepareCommandExecute(const std::shared_ptr<CommandMessage>& message);
void StartCommandExecute(const std::shared_ptr<CommandMessage>& message);

HRESULT ExecuteNextCommand();

Expand Down
8 changes: 8 additions & 0 deletions src/OrcLib/CommandMessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ CommandMessage::Message CommandMessage::MakeCancelAnyPendingAndStopMessage()
return retval;
}

CommandMessage::Message CommandMessage::MakeStartMessage(const std::wstring& keyword, DWORD dwProcessID)
{
auto retval = std::make_shared<::CommandMessageT>(CommandMessage::Start);
retval->m_dwPid = dwProcessID;
retval->m_Keyword = keyword;
return retval;
}

CommandMessage::Message CommandMessage::MakeTerminateMessage(DWORD dwProcessID)
{
auto retval = std::make_shared<::CommandMessageT>(CommandMessage::Terminate);
Expand Down
2 changes: 2 additions & 0 deletions src/OrcLib/CommandMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class CommandMessage
typedef enum _Request
{
Execute = 0,
Start,
Abort,
Terminate,
QueryRunningList,
Expand Down Expand Up @@ -112,6 +113,7 @@ class CommandMessage

static Message MakeCancelMessage();
static Message MakeAbortMessage(const std::wstring& keyword, DWORD processId, HANDLE hProcess);
static Message MakeStartMessage(const std::wstring& keyword, DWORD dwProcessID);
static Message MakeTerminateMessage(DWORD dwProcessID);
static Message MakeCancelAnyPendingAndStopMessage();
static Message MakeTerminateAllMessage();
Expand Down

0 comments on commit 617faba

Please sign in to comment.