Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions source/code/include/scxcorelib/scxprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ namespace SCXCoreLib
virtual ~SCXProcess();
void Kill();
unsigned GetEffectiveTimeout(unsigned timeout);
std::wstring ConstructShellCommandWithElevation(const std::wstring &command, const std::wstring &elevationtype);

protected:
virtual bool ReadToStream(int fd, std::ostream& stream);
Expand Down
46 changes: 45 additions & 1 deletion source/code/scxcorelib/pal/scxprocess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <scxcorelib/scxmath.h>
#include <scxcorelib/scxthread.h>
#include <scxcorelib/scxexception.h>
#include <scxsystemlib/scxsysteminfo.h>

#include <iostream>
#include <stdio.h>
Expand Down Expand Up @@ -798,10 +799,53 @@ namespace SCXCoreLib
{
if (killpg(m_pid, SIGKILL) < 0 && errno != ESRCH)
{
throw SCXInternalErrorException(UnexpectedErrno(L"Unable to kill child process group", errno), SCXSRCLOCATION);
// EPERM because the child omiagent process is not running as root (sudo)
// and thus will not have priviledges to send signals to this root (sudo) process
if (errno == EPERM)
{
std::istringstream processInput;
std::ostringstream processOutput;
std::ostringstream processError;

wchar_t procId[10];
swprintf(procId, 10, L"%d", m_pid);

std::wstring command(L"kill -9 ");
command += procId;
std::wstring elevatedCommand = ConstructShellCommandWithElevation(command, L"sudo");

// best effort to try to kill this using "kill" command with SUDO elevation
// we don't need any error handling here because this will throw an exception if something happens
// and that will get logged in scx log and this it a best effort in trying to kill the process
SCXCoreLib::SCXProcess::Run(SplitCommand(elevatedCommand), processInput, processOutput, processError, 5000);
}
else
{
throw SCXInternalErrorException(UnexpectedErrno(L"Unable to kill child process group", errno), SCXSRCLOCATION);
}
}
}

/**********************************************************************************/
//! Construct shell command with elevation
std::wstring SCXProcess::ConstructShellCommandWithElevation(const std::wstring &command,
const std::wstring &elevationtype)
{
SCXSystemLib::SystemInfo si;

std::wstring newCommand(si.GetShellCommand(command));

// Only when current user is not priviledged and elevation type is sudo
// the command need to be elevated.
// Force a shell command so we get a shell (even if already elevated)
if (elevationtype == L"sudo")
{
newCommand = si.GetElevatedCommand(newCommand);
}

return newCommand;
}

/**********************************************************************************/
//! Terminate the parent process, explicitly closing STDIN/OUT/ERR (so they flush)
void SCXProcess::CloseAndDie()
Expand Down
30 changes: 23 additions & 7 deletions source/code/scxcorelib/pal/scxthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <scxcorelib/scxthread.h>
#include <scxcorelib/stringaid.h>
#include <scxcorelib/scxstream.h>
#include <scxcorelib/scxlog.h>
#include <sstream>
#if defined(WIN32)
#elif defined(SCX_UNIX)
Expand Down Expand Up @@ -62,12 +63,12 @@ namespace SCXCoreLib
void* _InternalThreadStartRoutine(void* param)
#endif
{
int retCode = 0;
ThreadStartParams* p = static_cast<ThreadStartParams*>(param);
SCXASSERT(p != 0);

if (p->body != 0)
{
#if !defined(_DEBUG)
try
{
p->body( p->param );
Expand All @@ -76,20 +77,35 @@ namespace SCXCoreLib
{
SCXASSERTFAIL(std::wstring(L"ThreadStartRoutine() Thread threw unhandled exception - ").
append(e1.What()).append(L" - ").append(e1.Where()).c_str());

// We don't want to have the log variable as a member variable,
// because we don't want to open a new handle on every new thread, but rather only on exception
SCXCoreLib::SCXLogHandle log = SCXLogHandleFactory::GetLogHandle(std::wstring(L"scx.core.common.pal.process"));
SCX_LOGERROR(log, e1.What());

retCode = -1;
}
catch (const std::exception& e2)
{
SCXASSERTFAIL(std::wstring(L"ThreadStartRoutine() Thread threw unhandled exception - ").
append(StrFromUTF8(e2.what())).c_str());

// We don't want to have the log variable as a member variable,
// because we don't want to open a new handle on every new thread, but rather only on exception
SCXCoreLib::SCXLogHandle log = SCXLogHandleFactory::GetLogHandle(std::wstring(L"scx.core.common.pal.process"));
SCX_LOGERROR(log, e2.what());

retCode = -1;
}
#else
p->body( p->param );
#endif
/* We would like to catch (...) as well but it seemes we can't since there is a bug
in gcc. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28145 */
}

delete p;
return 0;

#if defined(WIN32)
return reinterpret_cast<DWORD>(retCode);
#elif defined(SCX_UNIX)
return reinterpret_cast<void*>(retCode);
#endif
}
}

Expand Down