266
struct UnicodeStringLess
270
operator()(const wstring& lhs, const wstring& rhs) const
272
int r = CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, lhs.c_str(), -1, rhs.c_str(), -1);
274
return r == CSTR_LESS_THAN;
271
282
Activator::Activator(const TraceLevelsPtr& traceLevels) :
354
365
// Get the absolute pathname of the executable.
356
char absbuf[_MAX_PATH];
358
string ext = path.size() <= 4 || path[path.size() - 4] != '.' ? ".exe" : "";
359
if(SearchPath(NULL, path.c_str(), ext.c_str(), _MAX_PATH, absbuf, &filePart) == 0)
367
wchar_t absbuf[_MAX_PATH];
369
wstring ext = path.size() <= 4 || path[path.size() - 4] != '.' ? L".exe" : L"";
370
if(SearchPathW(NULL, IceUtil::stringToWstring(path).c_str(), ext.c_str(), _MAX_PATH, absbuf, &fPart) == 0)
361
372
if(_traceLevels->activator > 0)
478
wstring wpwd = IceUtil::stringToWstring(pwd);
479
const wchar_t* dir = !wpwd.empty() ? wpwd.c_str() : NULL;
483
482
// Make a copy of the command line.
485
484
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
486
char* cmdbuf = _strdup(cmd.c_str());
485
wchar_t* cmdbuf = _wcsdup(IceUtil::stringToWstring(cmd).c_str());
488
char* cmdbuf = strdup(cmd.c_str());
487
wchar_t* cmdbuf = wcsdup(IceUtil::stringToWstring(cmd).c_str());
494
493
// Since Windows is case insensitive wrt environment variables we convert the keys to
495
494
// uppercase to ensure matches are found.
497
const char* env = NULL;
496
const wchar_t* env = NULL;
499
498
if(!envs.empty())
501
map<string, string> envMap;
502
LPVOID parentEnv = GetEnvironmentStrings();
503
const char* var = reinterpret_cast<const char*>(parentEnv);
500
map<wstring, wstring, UnicodeStringLess> envMap;
501
LPVOID parentEnv = GetEnvironmentStringsW();
502
const wchar_t* var = reinterpret_cast<const wchar_t*>(parentEnv);
507
506
// The environment block may start with some information about the
508
507
// current drive and working directory. This is indicated by a leading
509
508
// '=' character, so we skip to the first '\0' byte.
518
string::size_type pos = s.find('=');
519
if(pos != string::npos)
517
wstring::size_type pos = s.find(L'=');
518
if(pos != wstring::npos)
521
string key = IceUtilInternal::toUpper(s.substr(0, pos));
522
envMap.insert(map<string, string>::value_type(key, s.substr(pos + 1)));
520
envMap[s.substr(0, pos)] = s.substr(pos + 1);
525
523
var++; // Skip the '\0' byte
527
FreeEnvironmentStrings(static_cast<char*>(parentEnv));
525
FreeEnvironmentStringsW(static_cast<wchar_t*>(parentEnv));
528
526
for(p = envs.begin(); p != envs.end(); ++p)
531
string::size_type pos = s.find('=');
532
if(pos != string::npos)
528
wstring s = IceUtil::stringToWstring(*p);
529
wstring::size_type pos = s.find(L'=');
530
if(pos != wstring::npos)
534
string key = IceUtilInternal::toUpper(s.substr(0, pos));
536
envMap.insert(map<string, string>::value_type(key, s.substr(pos + 1)));
532
envMap[s.substr(0, pos)] = s.substr(pos + 1);
539
for(map<string, string>::const_iterator q = envMap.begin(); q != envMap.end(); ++q)
536
for(map<wstring, wstring, UnicodeStringLess>::const_iterator q = envMap.begin(); q != envMap.end(); ++q)
541
538
envbuf.append(q->first);
542
envbuf.push_back('=');
539
envbuf.push_back(L'=');
543
540
envbuf.append(q->second);
544
envbuf.push_back('\0');
541
envbuf.push_back(L'\0');
546
envbuf.push_back('\0');
543
envbuf.push_back(L'\0');
547
544
env = envbuf.c_str();
553
550
ZeroMemory(&si, sizeof(si));
554
551
si.cb = sizeof(si);
556
553
PROCESS_INFORMATION pi;
557
554
ZeroMemory(&pi, sizeof(pi));
559
BOOL b = CreateProcess(
555
BOOL b = CreateProcessW(
560
556
NULL, // Executable
561
557
cmdbuf, // Command line
562
558
NULL, // Process attributes
563
559
NULL, // Thread attributes
564
560
FALSE, // Do NOT inherit handles
565
CREATE_NEW_PROCESS_GROUP, // Process creation flags
561
CREATE_NEW_PROCESS_GROUP | CREATE_UNICODE_ENVIRONMENT, // Process creation flags
566
562
(LPVOID)env, // Process environment
567
563
dir, // Current directory
568
564
&si, // Startup info
1377
1372
Activator::waitPid(pid_t processPid)
1380
1377
#if defined(__linux)
1382
while(true) // The while loop is necessary for the linux workaround.
1379
while(true) // The while loop is necessary for the linux workaround.
1381
pid_t pid = waitpid(processPid, &status, 0);
1385
// Some Linux distribution have a bogus waitpid() (e.g.: CentOS 4.x). It doesn't
1386
// block and reports an incorrect ECHILD error on the first call. We sleep a
1387
// little and retry to work around this issue (it appears from testing that a
1388
// single retry is enough but to make sure we retry up to 10 times before to throw.)
1390
if(errno == ECHILD && nRetry < 10)
1392
// Wait 1ms, 11ms, 21ms, etc.
1393
IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(nRetry * 10 + 1));
1397
SyscallException ex(__FILE__, __LINE__);
1398
ex.error = getSystemErrno();
1401
assert(pid == processPid);
1384
1405
pid_t pid = waitpid(processPid, &status, 0);
1388
// Some Linux distribution have a bogus waitpid() (e.g.: CentOS 4.x). It doesn't
1389
// block and reports an incorrect ECHILD error on the first call. We sleep a
1390
// little and retry to work around this issue (it appears from testing that a
1391
// single retry is enough but to make sure we retry up to 10 times before to throw.)
1393
if(errno == ECHILD && nRetry < 10)
1395
// Wait 1ms, 11ms, 21ms, etc.
1396
IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(nRetry * 10 + 1));
1400
1408
SyscallException ex(__FILE__, __LINE__);
1401
1409
ex.error = getSystemErrno();
1404
1412
assert(pid == processPid);
1408
pid_t pid = waitpid(processPid, &status, 0);
1416
catch(const Ice::LocalException& ex)
1411
SyscallException ex(__FILE__, __LINE__);
1412
ex.error = getSystemErrno();
1418
Error out(_traceLevels->logger);
1419
out << "unable to get process status:\n" << ex;
1415
assert(pid == processPid);