Changes: Booster::renameProcess() refactored.

RevBy: Antti Kervinen

Details: New arguments copied as a contiguous, NULL-separated block. Unit tests refactored.
pull/1/head
Jussi Lind 15 years ago
parent 059e582cf0
commit 1d459029c2

@ -49,9 +49,9 @@
Booster::Booster() :
m_appData(new AppData),
m_connection(NULL),
m_argvArraySize(0),
m_oldPriority(0),
m_oldPriorityOk(false)
m_oldPriorityOk(false),
m_spaceAvailable(0)
{}
Booster::~Booster()
@ -80,7 +80,8 @@ void Booster::initialize(int initialArgc, char ** initialArgv, int newPipeFd[2],
preload();
// Rename process to temporary booster process name, e.g. "booster-m"
renameProcess(initialArgc, initialArgv);
const char * tempArgv[] = {boosterTemporaryProcessName().c_str()};
renameProcess(initialArgc, initialArgv, 1, tempArgv);
// Restore priority
popPriority();
@ -121,7 +122,7 @@ void Booster::initialize(int initialArgc, char ** initialArgv, int newPipeFd[2],
// Give the process the real application name now that it
// has been read from invoker in receiveDataFromInvoker().
renameProcess(initialArgc, initialArgv);
renameProcess(initialArgc, initialArgv, m_appData->argc(), m_appData->argv());
// Send parent process a message that it can create a new booster,
// send pid of invoker, send booster respawn value
@ -222,62 +223,117 @@ void Booster::run(SocketManager * socketManager)
}
}
void Booster::renameProcess(int parentArgc, char** parentArgv)
void Booster::renameProcess(int parentArgc, char** parentArgv,
int sourceArgc, const char** sourceArgv)
{
if (m_argvArraySize == 0)
if (sourceArgc > 0 && parentArgc > 0)
{
// rename process for the first time
// calculate and store size of parentArgv array
// Calculate original space reserved for arguments, if not
// already calculated
if (!m_spaceAvailable)
for (int i = 0; i < parentArgc; i++)
m_argvArraySize += strlen(parentArgv[i]) + 1;
m_argvArraySize--;
}
m_spaceAvailable += strlen(parentArgv[i]) + 1;
if (m_appData->appName().empty())
if (m_spaceAvailable)
{
// application name isn't known yet, let's give to the process
// temporary booster name
m_appData->setAppName(boosterTemporaryProcessName());
// Build a contiguous, NULL-separated block for the new arguments.
// This is how Linux puts them.
std::string newArgv;
for (int i = 0; i < sourceArgc; i++)
{
newArgv += sourceArgv[i];
newArgv += '\0';
}
const char* newProcessName = m_appData->appName().c_str();
Logger::logNotice("Booster: set new name for process: %s", newProcessName);
const int spaceNeeded = std::min(m_spaceAvailable,
static_cast<int>(newArgv.size()));
// This code copies all the new arguments to the space reserved
// in the old argv array. If an argument won't fit then the algorithm
// leaves it fully out and terminates.
// Reset the old space
memset(parentArgv[0], '\0', m_spaceAvailable);
int spaceAvailable = m_argvArraySize;
if (spaceAvailable > 0)
if (spaceNeeded > 0)
{
memset(parentArgv[0], '\0', spaceAvailable);
strncat(parentArgv[0], newProcessName, spaceAvailable);
spaceAvailable -= strlen(parentArgv[0]);
// Copy the argument data. Note: if they don't fit, then
// they are just cut off.
memcpy(parentArgv[0], newArgv.c_str(), spaceNeeded);
for (int i = 1; i < m_appData->argc(); i++)
{
if (spaceAvailable > static_cast<int>(strlen(m_appData->argv()[i])) + 1)
{
strncat(parentArgv[0], " ", 1);
strncat(parentArgv[0], m_appData->argv()[i], spaceAvailable);
spaceAvailable -= strlen(m_appData->argv()[i] + 1);
}
else
{
break;
}
// Ensure NULL at the end
parentArgv[0][spaceNeeded - 1] = '\0';
}
}
// Set the process name using prctl, 'killall' and 'top' use it
if ( prctl(PR_SET_NAME, basename(newProcessName)) == -1 )
if ( prctl(PR_SET_NAME, basename(sourceArgv[0])) == -1 )
Logger::logError("Booster: on set new process name: %s ", strerror(errno));
setenv("_", newProcessName, true);
}
setenv("_", sourceArgv[0], true);
}
}
//void Booster::renameProcess(int parentArgc, char** parentArgv)
//{
// if (m_argvArraySize == 0)
// {
// // rename process for the first time
// // calculate and store size of parentArgv array
// for (int i = 0; i < parentArgc; i++)
// m_argvArraySize += strlen(parentArgv[i]) + 1;
// }
// if (m_appData->appName().empty())
// {
// // application name isn't known yet, let's give to the process
// // temporary booster name
// m_appData->setAppName(boosterTemporaryProcessName());
// }
// else
// {
// const char* newProcessName = m_appData->appName().c_str();
// Logger::logNotice("Booster: set new name for process: %s", newProcessName);
// // This code copies all the new arguments to the space reserved
// // in the old argv array. If an argument won't fit then the algorithm
// // leaves it fully out and terminates.
// int spaceAvailable = m_argvArraySize;
// if (spaceAvailable > 0)
// {
// memset(parentArgv[0], '\0', spaceAvailable);
// int spaceNeeded = 0;
// for (int i = 0; i < m_appData->argc(); i++)
// spaceNeeded += strlen(m_appData->argv()[i]) + 1;
// // memset(parentArgv[0], '\0', spaceAvailable);
// // strncat(parentArgv[0], newProcessName, spaceAvailable);
// // spaceAvailable -= strlen(parentArgv[0]);
// memcpy(parentArgv[0], m_appData->argv()[0],
// std::min(spaceAvailable, spaceNeeded));
// // for (int i = 1; i < m_appData->argc(); i++)
// // {
// // if (spaceAvailable > static_cast<int>(strlen(m_appData->argv()[i])) + 1)
// // {
// // strncat(parentArgv[0], " ", 1);
// // strncat(parentArgv[0], m_appData->argv()[i], spaceAvailable);
// // spaceAvailable -= strlen(m_appData->argv()[i] + 1);
// // }
// // else
// // {
// // break;
// // }
// // }
// }
// }
// // Set the process name using prctl, 'killall' and 'top' use it
// if ( prctl(PR_SET_NAME, basename(newProcessName)) == -1 )
// Logger::logError("Booster: on set new process name: %s ", strerror(errno));
// setenv("_", newProcessName, true);
//}
int Booster::launchProcess()
{

@ -104,7 +104,10 @@ public:
* \param initialArgc Number of the arguments of the launcher process.
* \param initialArgv Address of the argument array of the launcher process.
*/
void renameProcess(int initialArgc, char** initialArgv);
// void renameProcess(int initialArgc, char** initialArgv);
void renameProcess(int parentArgc, char** parentArgv,
int sourceArgc, const char** sourceArgv);
/*!
* \brief Return booster type common to all instances.
@ -197,9 +200,6 @@ private:
//! Socket connection to invoker
Connection* m_connection;
//! Size (length) of the argument vector
int m_argvArraySize;
//! Process priority before pushPriority() is called
int m_oldPriority;
@ -210,6 +210,9 @@ private:
//! Pipe used to tell the parent that a new booster is needed
int m_pipeFd[2];
//! Original space available for arguments
int m_spaceAvailable;
#ifdef HAVE_CREDS
//! filter out invoker-specific credentials from boosted application
static void filterOutCreds(creds_t creds);

@ -1,15 +1,10 @@
#!/bin/sh
# Forces resolving symbols of libraries to which applauncherd.bin is
# linked to.
# commented out because of broken libamjpeg library
# export LD_BIND_NOW=1
# Use 50 chars long dummy parameter to reserve place for application
# name and parameters so that we get some space to modify them
# afterwards. If the length of the application name with parameters is
# longer than space available, only the params that fully fit will be
# shown in the output of top and ps commands.
# name and parameters so that we get some space to modify the argument
# list seen in /proc/[PID]/cmdline.
# If the length of the application name with parameters is longer than space
# available, parameters will be cut off. The main function will still always
# get the complete argument list.
exec /usr/bin/applauncherd.bin " "

@ -79,61 +79,37 @@ char ** Ut_Booster::packTwoArgs(const char * arg0, const char * arg1)
return argv;
}
void Ut_Booster::testRenameBoosterProcess()
void Ut_Booster::testRenameProcess()
{
m_subject.reset(new MyBooster);
// if appData()->appName isn't initialized, new process name is booster_x
// If appData()->appName isn't initialized, new process name is booster_x
// 20 chars dummy buffer used to fool ps to show correct process name with args
const int INIT_ARGS = 2;
const int INIT_ARGC = 2;
char ** initialArgv = packTwoArgs("oldName", " ");
m_subject->renameProcess(INIT_ARGS, const_cast<char **>(initialArgv));
// New name and arguments fit and are correct
// Rename process
const char * tempArgv[] = {m_subject->boosterTemporaryProcessName().c_str()};
m_subject->renameProcess(INIT_ARGC, initialArgv, 1, tempArgv);
// Check that new name and arguments fit and are correct
QVERIFY(strcmp(initialArgv[0], m_subject->boosterTemporaryProcessName().c_str()) == 0);
// Define and copy args because it's assumed that they are allocated in the heap
// (AppData deletes the argv on exit)
const int ARGS = 3;
m_subject->appData()->setArgc(ARGS);
const int ARGC = 3;
m_subject->appData()->setArgc(ARGC);
char ** argv = new char * [ARGS];
char ** argv = new char * [ARGC];
argv[0] = strdup("newName");
argv[1] = strdup("--foo");
argv[2] = strdup("--bar");
m_subject->appData()->setArgv(const_cast<const char **>(argv));
m_subject->appData()->setAppName("newName");
m_subject->renameProcess(INIT_ARGS, const_cast<char **>(initialArgv));
m_subject->renameProcess(INIT_ARGC, initialArgv, ARGC, const_cast<const char **>(argv));
// New name and arguments fit and are correct
QVERIFY2(strcmp(initialArgv[0], "newName --foo --bar") == 0, initialArgv[0]);
delete initialArgv[0];
delete [] initialArgv;
}
void Ut_Booster::testRenameProcess()
{
m_subject.reset(new MyBooster);
// Define and copy args because it's assumed that they are allocated in the heap
// (AppData deletes the argv on exit)
const int ARGS = 3;
m_subject->appData()->setArgc(ARGS);
char ** argv = new char * [ARGS];
argv[0] = strdup("newName");
argv[1] = strdup("--foo");
argv[2] = strdup("--bar");
m_subject->appData()->setArgv(const_cast<const char **>(argv));
m_subject->appData()->setAppName(m_subject->appData()->argv()[0]);
// 20 chars dummy buffer used to fool ps to show correct process name with args
const int INIT_ARGS = 2;
char ** initialArgv = packTwoArgs("oldName", " ");
m_subject->renameProcess(INIT_ARGS, const_cast<char **>(initialArgv));
// New name and arguments fit and are correct
QVERIFY(strcmp(initialArgv[0], "newName --foo --bar") == 0);
const char * result = "newName\0--foo\0--bar\0";
QVERIFY2(memcmp(initialArgv[0], result, 20) == 0, initialArgv[0]);
delete initialArgv[0];
delete [] initialArgv;
@ -143,125 +119,25 @@ void Ut_Booster::testRenameProcessNotEnoughSpace()
{
m_subject.reset(new MyBooster);
const int ARGS = 3;
m_subject->appData()->setArgc(ARGS);
char ** argv = new char * [ARGS];
const int NEW_ARGC = 3;
m_subject->appData()->setArgc(NEW_ARGC);
char ** argv = new char * [NEW_ARGC];
argv[0] = strdup("newNameLong");
argv[1] = strdup("--foo");
argv[2] = strdup("--bar");
m_subject->appData()->setArgv(const_cast<const char **>(argv));
m_subject->appData()->setAppName(m_subject->appData()->argv()[0]);
const int INIT_ARGS = 2;
char ** initialArgv = packTwoArgs("oldName", " ");
int initLen = strlen(initialArgv[0]);
m_subject->renameProcess(INIT_ARGS, initialArgv);
const int INIT_ARGC = 2;
char ** initialArgv = packTwoArgs("old0123", "");
int initLen = strlen(initialArgv[0]) + 1 + strlen("");
m_subject->renameProcess(INIT_ARGC, initialArgv,
m_subject->appData()->argc(), m_subject->appData()->argv());
// Not enough space for the new name nor the arguments:
// name should be cut
QVERIFY(strncmp(initialArgv[0], m_subject->appData()->argv()[0], initLen - 1) == 0);
delete [] initialArgv[0];
delete [] initialArgv;
}
void Ut_Booster::testRenameProcessNotEnoughSpace2()
{
m_subject.reset(new MyBooster);
const int ARGS = 3;
m_subject->appData()->setArgc(ARGS);
char ** argv = new char * [ARGS];
argv[0] = strdup("newName");
argv[1] = strdup("--foo");
argv[2] = strdup("--bar");
m_subject->appData()->setArgv(const_cast<const char **>(argv));
m_subject->appData()->setAppName(m_subject->appData()->argv()[0]);
const int INIT_ARGS = 2;
char ** initialArgv = packTwoArgs("oldName", " ");
m_subject->renameProcess(INIT_ARGS, initialArgv);
// Not enough space for the second argument:
// second argument should be left out
QVERIFY(strcmp(initialArgv[0], "newName --foo") == 0);
delete initialArgv[0];
delete [] initialArgv;
}
void Ut_Booster::testRenameProcessNotEnoughSpace3()
{
m_subject.reset(new MyBooster);
const int ARGS = 3;
m_subject->appData()->setArgc(ARGS);
char ** argv = new char * [ARGS];
argv[0] = strdup("newName");
argv[1] = strdup("--foo");
argv[2] = strdup("--bar");
m_subject->appData()->setArgv(const_cast<const char **>(argv));
m_subject->appData()->setAppName(m_subject->appData()->argv()[0]);
const int INIT_ARGS = 2;
char ** initialArgv = packTwoArgs("app", " ");
m_subject->renameProcess(INIT_ARGS, initialArgv);
// Not enough space for arguments but just enough space
// for the new name
QVERIFY(strcmp(initialArgv[0], "newName") == 0);
delete initialArgv[0];
delete [] initialArgv;
}
void Ut_Booster::testRenameProcessNotEnoughSpace4()
{
m_subject.reset(new MyBooster);
const int ARGS = 3;
m_subject->appData()->setArgc(ARGS);
char ** argv = new char * [ARGS];
argv[0] = strdup("newNameLongLong");
argv[1] = strdup("--foo");
argv[2] = strdup("--bar");
m_subject->appData()->setArgv(const_cast<const char **>(argv));
m_subject->appData()->setAppName(m_subject->appData()->argv()[0]);
const int INIT_ARGS = 2;
char ** initialArgv = packTwoArgs("app", " ");
m_subject->renameProcess(INIT_ARGS, initialArgv);
// Not enough space for newName, but dummy space exist: should be cut
QVERIFY(strcmp(initialArgv[0], "newName") == 0);
delete initialArgv[0];
delete [] initialArgv;
}
void Ut_Booster::testRenameProcessNoArgs()
{
m_subject.reset(new MyBooster);
const int ARGS = 2;
m_subject->appData()->setArgc(ARGS);
char ** argv = new char * [ARGS];
argv[0] = strdup("newName");
argv[1] = strdup("--foo");
m_subject->appData()->setArgv(const_cast<const char **>(argv));
m_subject->appData()->setAppName(m_subject->appData()->argv()[0]);
const int INIT_ARGS = 1;
char ** initialArgv = new char * [INIT_ARGS];
initialArgv[0] = strdup("oldName");
m_subject->renameProcess(INIT_ARGS, initialArgv);
// No dummy space argument at all, only name fits
QVERIFY(strcmp(initialArgv[0], m_subject->appData()->argv()[0]) == 0);
delete initialArgv[0];
delete [] initialArgv;
QVERIFY(memcmp(initialArgv[0], m_subject->appData()->argv()[0], initLen) == 0);
QVERIFY(initialArgv[0][initLen] == '\0');
QVERIFY(initialArgv[0][initLen - 1] == 'L');
}
QTEST_APPLESS_MAIN(Ut_Booster);

@ -37,11 +37,6 @@ private Q_SLOTS:
void initTestCase();
void testRenameProcess();
void testRenameProcessNotEnoughSpace();
void testRenameProcessNotEnoughSpace2();
void testRenameProcessNotEnoughSpace3();
void testRenameProcessNotEnoughSpace4();
void testRenameProcessNoArgs();
void testRenameBoosterProcess();
void cleanupTestCase();
private:
@ -51,5 +46,3 @@ private:
};
#endif // UT_BOOSTER_H

Loading…
Cancel
Save