9 #define _CRT_SECURE_NO_WARNINGS
19#include <mach/vm_statistics.h>
21#include <mach/host_info.h>
22#include <mach/task_info.h>
23#include <mach/thread_act.h>
24#include <sys/sysctl.h>
31#include <condition_variable>
66 std::map<std::string, utils::Semaphore*>::iterator si;
81 std::map<std::string, utils::Event*>::iterator ei;
96 std::map<std::string, utils::Mutex*>::iterator mi;
145 return "String info";
147 return "Binary info";
149 return "Message info";
151 return "Unknown type";
156 if ((
stricmp(typeName,
"string") == 0) || (
stricmp(typeName,
"text") == 0))
158 else if (
stricmp(typeName,
"time") == 0)
160 else if ((
stricmp(typeName,
"integer") == 0) || (
stricmp(typeName,
"int") == 0))
162 else if ((
stricmp(typeName,
"float") == 0) || (
stricmp(typeName,
"double") == 0))
164 else if (
stricmp(typeName,
"binary") == 0)
166 else if (
stricmp(typeName,
"message") == 0)
168 else if (
stricmp(typeName,
"string info") == 0)
170 else if (
stricmp(typeName,
"binary info") == 0)
172 else if (
stricmp(typeName,
"message info") == 0)
255 return (
char*)
this+
sizeof(
LogEntry);
264 if (avail < (int32)len)
266 memcpy((
char*)
this+
sizeof(
LogEntry), text, len);
267 *((
char*)
this+
sizeof(
LogEntry)+len) = 0;
273 const char* text =
getText(len);
275 "{ \"time\": %llu, \"level\": %u, \"source\": %u, \"subject\": %u, \"type\": %u, \"text\": \"%s\" }",
281 const char* text =
getText(len);
283 "<entry time=\"%llu\" level=\"%u\" source=\"%u\" subject=\"%u\" type=\"%u\" text=\"%s\" />\n",
335 va_start(args, formatstring);
348 entry->
level = level;
359 std::cout << strline;
383 va_start(args, formatstring);
396 entry->
level = level;
417 static int macos_pthread_mutex_timedlock(pthread_mutex_t *mutex,
const struct timespec *abs_timeout)
427 while ((rv = pthread_mutex_trylock(mutex)) == EBUSY) {
429 gettimeofday(&now, NULL);
430 if (now.tv_sec > abs_timeout->tv_sec ||
431 (now.tv_sec == abs_timeout->tv_sec &&
432 (
long)(now.tv_usec) * 1000L >= abs_timeout->tv_nsec))
434 struct timespec nap = { 0, 1000000 };
435 nanosleep(&nap, NULL);
448 if (gettimeofday(&now, NULL) != 0)
451 timeout.tv_sec = now.tv_sec + (ms / 1000);
452 int64 us = (int64)(now.tv_usec) + ((ms % 1000)*1000);
453 while (us >= 1000000) {
457 timeout.tv_nsec = (long)(us * 1000);
463 if ( gettimeofday(&tv, NULL))
465 return (tv.tv_usec + tv.tv_sec * 1000000LL);
472 VOID CALLBACK
DrumBeatCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired) {
473 DrumBeatInfo* info = (DrumBeatInfo*) lpParameter;
475 if (!info->id || !info->createdTime || !info->started || !func)
478 if (!info->func(info->id, info->count))
519 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
520 dispatch_source_t timer_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
522 info->
handle = timer_source;
525 struct sigevent timer_event;
532 timer_event.sigev_notify = SIGEV_THREAD;
533 timer_event.sigev_notify_attributes = NULL;
535 timer_event.sigev_value.sival_ptr = (
void *)info;
536 int ret = timer_create(CLOCK_REALTIME, &timer_event, &info->
handle);
565 uint64 intervalNs = (uint64)info->
interval * 1000000;
566 dispatch_source_set_timer(info->
handle, dispatch_time(DISPATCH_TIME_NOW, (int64_t)intervalNs), intervalNs, 0);
568 dispatch_source_set_event_handler(info->
handle, ^{
570 if (!inf->func(inf->id, inf->count))
571 StopDrumBeat(inf->id);
573 dispatch_resume(info->
handle);
577 struct itimerspec newtv;
579 newtv.it_interval.tv_sec = p / 1000000;
580 newtv.it_interval.tv_nsec = (p % 1000000)*1000;
581 newtv.it_value.tv_sec = p / 1000000;
582 newtv.it_value.tv_nsec = (p % 1000000)*1000;
584 int ret = timer_settime(info->
handle, 0, &newtv, NULL);
605 DeleteTimerQueueTimer(NULL, info->
handle, NULL);
611 dispatch_suspend(info->
handle);
615 struct itimerspec newtv;
616 memset(&newtv, 0,
sizeof(itimerspec));
617 int ret = timer_settime(info->
handle, 0, &newtv, NULL);
649 dispatch_source_cancel(info->
handle);
651 dispatch_resume(info->
handle);
652 dispatch_release(info->
handle);
657 timer_delete(info->
handle);
671bool EnterMutex(
const char* name, uint32 ms,
bool autocreate) {
688 mutex =
new Mutex(name);
700 mutex =
new Mutex(name);
708 return (mutex->
enter(ms));
721 return (i->second->leave());
770 semaphore = i->second;
783 semaphore = i->second;
809 semaphore = i->second;
822 semaphore = i->second;
823 return (semaphore->
wait(ms));
845 semaphore = i->second;
854 semaphore = i->second;
855 return (semaphore->
signal());
903 event =
new Event(name);
915 event =
new Event(name);
936 return (i->second->signal());
999 #if defined(__GNUC__) || defined(__clang__)
1026 (*g_cancelSafeSet)[
this] =
true;
1052 mutex =
new pthread_mutex_t;
1053 pthread_mutexattr_t attr;
1054 pthread_mutexattr_init(&attr);
1055 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1056 pthread_mutex_init(
mutex, &attr);
1064 pthread_mutexattr_destroy(&attr);
1077 mutex = ::CreateMutex(NULL,
FALSE, this->name);
1091 mutex = (pthread_mutex_t*) data;
1098 mutex = (pthread_mutex_t*) data;
1099 pthread_mutexattr_t attr;
1100 pthread_mutexattr_init(&attr);
1101 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
1102 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1103 pthread_mutex_init(
mutex, &attr);
1104 pthread_mutexattr_destroy(&attr);
1111bool CloseMutexHandle(HANDLE mutex) {
1117 __except (EXCEPTION_EXECUTE_HANDLER) {
1138 CloseMutexHandle(
mutex);
1143 pthread_mutex_destroy(
mutex);
1149 pthread_mutex_destroy(
mutex);
1161 reply = WaitForSingleObject(
mutex, INFINITE);
1166 if (reply == WAIT_OBJECT_0 || reply == WAIT_ABANDONED) {
1174 else if (reply == WAIT_FAILED && GetLastError() == ERROR_INVALID_HANDLE) {
1192 int prevCancelState = 0;
1194 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &prevCancelState);
1195 int error = pthread_mutex_lock(
mutex);
1200 if (cs &&
count == 0)
1207 pthread_setcancelstate(prevCancelState, NULL);
1222 reply = WaitForSingleObject(
mutex, timeout);
1224 if (reply == WAIT_OBJECT_0 || reply == WAIT_ABANDONED) {
1240 if (reply == WAIT_TIMEOUT) {
1241 LogPrint(0,
LOG_SYSTEM, 0,
"[%u]Mutex enter timeout[%p](%s) - currently held by %u, count %u, total %u",
1246 else if (reply == WAIT_FAILED) {
1247 DWORD mtxErr = GetLastError();
1248 if (mtxErr == ERROR_INVALID_HANDLE)
1250 char* msg =
new char[2048];
1251 int length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
1252 NULL, mtxErr, 0, msg, 2048, NULL);
1254 LogPrint(0,
LOG_SYSTEM, 0,
"[%u]Mutex enter failed[%p](%s): %s - currently held by %u, count %u, total %u",
1260 LogPrint(0,
LOG_SYSTEM,0,
"[%u]Mutex enter error[%p](%s): %d - currently held by %u, count %u, total %u",
1270 int prevCancelState = 0;
1272 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &prevCancelState);
1274 int error = macos_pthread_mutex_timedlock(
mutex, &ts);
1276 int error = pthread_mutex_timedlock(
mutex, &ts);
1280 if (cs &&
count == 0)
1291 pthread_setcancelstate(prevCancelState, NULL);
1293 if (error == EINVAL) {
1295 errorMsg ? errorMsg :
"-", error, timeout, (uint64)(ts.tv_sec), (int64)(ts.tv_nsec));
1299 LogPrint(0,
LOG_SYSTEM,0,
"Mutex enter timeout %u: '%s' (%d) [%p] - held by %u", timeout, errorMsg ? errorMsg :
"-", error,
this,
osid);
1335 uint32 osid2 =
osid;
1343 if (ReleaseMutex(
mutex) != 0) {
1368 if (pthread_mutex_unlock(
mutex) != 0)
1374 pthread_setcancelstate(restoreState, NULL);
1416 semaphore_impl = dispatch_semaphore_create(0);
1441 snprintf(shmemname,
sizeof(shmemname),
"Semaphore_%s",
name);
1446 pthread_mutex_t* m = (pthread_mutex_t*)data;
1447 pthread_mutexattr_t attr;
1448 pthread_mutexattr_init(&attr);
1449 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
1450 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1451 pthread_mutex_init(m, &attr);
1452 pthread_mutexattr_destroy(&attr);
1453 pthread_cond_t* c = (pthread_cond_t*)(data +
sizeof(pthread_mutex_t));
1454 pthread_condattr_t cattr;
1455 pthread_condattr_init(&cattr);
1456 pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
1457 pthread_cond_init(c, &cattr);
1458 pthread_condattr_destroy(&cattr);
1459 uint32* cnt = (uint32*)(data +
sizeof(pthread_mutex_t) +
sizeof(pthread_cond_t));
1463 semaphore_impl = data;
1467 semaphore = sem_open(this->name, O_CREAT, 0666, 1);
1487 dispatch_release((dispatch_semaphore_t)semaphore_impl);
1488 semaphore_impl = NULL;
1491 if (semaphore_impl) {
1493 semaphore_impl = NULL;
1509 snprintf(semname,
sizeof(semname),
"/Semaphore_%s",
name);
1510 sem_unlink(semname);
1519 return (WaitForSingleObject(
semaphore, INFINITE) == WAIT_OBJECT_0);
1523 return dispatch_semaphore_wait((dispatch_semaphore_t)semaphore_impl, DISPATCH_TIME_FOREVER) == 0;
1525 char* data = (
char*)semaphore_impl;
1526 if (!data)
return false;
1527 pthread_mutex_t* m = (pthread_mutex_t*)data;
1528 pthread_cond_t* c = (pthread_cond_t*)(data +
sizeof(pthread_mutex_t));
1529 uint32* cnt = (uint32*)(data +
sizeof(pthread_mutex_t) +
sizeof(pthread_cond_t));
1530 pthread_mutex_lock(m);
1532 pthread_cond_wait(c, m);
1534 pthread_mutex_unlock(m);
1546 return (WaitForSingleObject(
semaphore, timeout) == WAIT_OBJECT_0);
1550 dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)timeout * 1000000);
1551 return dispatch_semaphore_wait((dispatch_semaphore_t)semaphore_impl, when) == 0;
1554 char* data = (
char*)semaphore_impl;
1555 if (!data)
return false;
1556 pthread_mutex_t* m = (pthread_mutex_t*)data;
1557 pthread_cond_t* c = (pthread_cond_t*)(data +
sizeof(pthread_mutex_t));
1558 uint32* cnt = (uint32*)(data +
sizeof(pthread_mutex_t) +
sizeof(pthread_cond_t));
1559 pthread_mutex_lock(m);
1563 int r = pthread_cond_timedwait(c, m, &t);
1564 if (r == ETIMEDOUT) {
1565 pthread_mutex_unlock(m);
1569 pthread_mutex_unlock(m);
1574 pthread_mutex_unlock(m);
1588 return (ReleaseSemaphore(
1595 return dispatch_semaphore_signal((dispatch_semaphore_t)semaphore_impl) != 0;
1597 char* data = (
char*)semaphore_impl;
1598 if (!data)
return false;
1599 pthread_mutex_t* m = (pthread_mutex_t*)data;
1600 pthread_cond_t* c = (pthread_cond_t*)(data +
sizeof(pthread_mutex_t));
1601 uint32* cnt = (uint32*)(data +
sizeof(pthread_mutex_t) +
sizeof(pthread_cond_t));
1602 pthread_mutex_lock(m);
1604 pthread_cond_signal(c);
1605 pthread_mutex_unlock(m);
1640 event = CreateEvent(
1646 event =
new pthread_cond_t;
1647 pthread_cond_init(
event, NULL);
1649 mutex =
new pthread_mutex_t;
1650 pthread_mutex_init(
mutex, NULL);
1660 event = CreateEvent(
1668 mutex = (pthread_mutex_t*) data;
1669 event = (pthread_cond_t*) (data +
sizeof(pthread_mutex_t));
1675 mutex = (pthread_mutex_t*) data;
1676 pthread_mutexattr_t attr;
1677 pthread_mutexattr_init(&attr);
1678 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
1679 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1680 pthread_mutex_init(
mutex, &attr);
1681 pthread_mutexattr_destroy(&attr);
1683 event = (pthread_cond_t*) (data +
sizeof(pthread_mutex_t));
1684 pthread_condattr_t cattr;
1685 pthread_condattr_init(&cattr);
1686 pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
1688 pthread_cond_init(
event, &cattr);
1689 pthread_mutexattr_destroy(&attr);
1704 pthread_cond_destroy(
event);
1706 pthread_mutex_destroy(
mutex);
1710 pthread_cond_destroy(
event);
1711 pthread_mutex_destroy(
mutex);
1722 return (WaitForSingleObject(
event, INFINITE) == WAIT_OBJECT_0);
1724 pthread_mutex_lock(
mutex);
1726 pthread_mutex_unlock(
mutex);
1733 return (WaitForSingleObject(
event, timeout) == WAIT_OBJECT_0);
1735 pthread_mutex_lock(
mutex);
1738 int r = pthread_cond_timedwait(
event,
mutex, &t);
1739 pthread_mutex_unlock(
mutex);
1746 if (!SetEvent(
event))
1752 pthread_mutex_lock(
mutex);
1753 int r = pthread_cond_broadcast(
event);
1754 pthread_mutex_unlock(
mutex);
1786 timers =
new std::map<uint32, Timer*>;
1790 (*timers)[globalID] =
this;
1798 std::map<uint32, TimerSchedule*>::iterator it = schedules.begin();
1799 std::map<uint32, TimerSchedule*>::iterator itEnd = schedules.end();
1805 std::list<TimerSchedule*>::iterator it2 = oldSchedules.begin();
1806 std::list<TimerSchedule*>::iterator it2End = oldSchedules.end();
1807 while (it2 != it2End)
1809 oldSchedules.clear();
1816 if (schedules[
id]) {
1825 schedule->
start = start;
1826 schedule->
end = end;
1828 schedules[id] = schedule;
1831 uint32 firstDelay = 0;
1832 if (start && (start > now))
1833 firstDelay = (uint32)(start - now)/1000;
1837 if (!CreateTimerQueueTimer(&schedule->
handle, NULL,
TimerCallback, schedule, firstDelay, interval, WT_EXECUTEINTIMERTHREAD)) {
1838 schedules[id] = NULL;
1845 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1846 dispatch_source_t timer_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
1847 if (!timer_source) {
1848 schedules[id] = NULL;
1853 schedule->
handle = timer_source;
1854 uint64 firstDelayNs = (uint64)firstDelay * 1000000;
1855 uint64 intervalNs = (uint64)interval * 1000000;
1856 dispatch_source_set_timer(timer_source, dispatch_time(DISPATCH_TIME_NOW, (int64_t)firstDelayNs), intervalNs, 0);
1857 dispatch_source_set_event_handler(timer_source, ^{
1867 dispatch_resume(timer_source);
1869 struct sigaction sa;
1870 struct sigevent timer_event;
1872 sigemptyset(&sa.sa_mask);
1873 sa.sa_flags = SA_SIGINFO;
1875 sigaction(SIGRTMIN, &sa, NULL);
1877 timer_event.sigev_notify = SIGEV_SIGNAL;
1878 timer_event.sigev_signo = SIGRTMIN;
1879 timer_event.sigev_value.sival_ptr = (
void *)schedule;
1880 if (timer_create(CLOCK_REALTIME, &timer_event, &schedule->
handle) != 0) {
1881 schedules[id] = NULL;
1887 struct itimerspec newtv;
1890 uint64 period = interval * 1000;
1891 newtv.it_value.tv_sec = firstDelay / 1000000;
1892 newtv.it_value.tv_nsec = (firstDelay % 1000000)*1000;
1893 newtv.it_interval.tv_sec = period / 1000000;
1894 newtv.it_interval.tv_nsec = (period % 1000000)*1000;
1896 if (timer_settime(schedule->
handle, 0, &newtv, NULL) != 0) {
1897 timer_delete(schedule->
handle);
1898 schedules[id] = NULL;
1903 sigemptyset(&allsigs);
1920 schedules[id] = NULL;
1923 DeleteTimerQueueTimer(NULL, schedule->
handle, NULL);
1926 dispatch_source_cancel(schedule->
handle);
1927 dispatch_release(schedule->
handle);
1929 timer_delete(schedule->
handle);
1933 oldSchedules.push_back(schedule);
1947 trigger->
id = schedule->
id;
1950 triggers.push(trigger);
1953 if ( schedule->
end && ((int32)(schedule->
end - trigger->
time) < (int32)schedule->
interval))
1966 while (!triggers.size()) {
1968 if ( (timeleft = (int32)timeout -
GetTimeAgeMS(start)) <= 0)
1970 semaphore.wait((uint32)timeleft);
1974 trigger = triggers.front();
1977 time = trigger->
time;
1984 void CALLBACK
TimerCallback(PVOID arg, BOOLEAN TimerOrWaitFired) {
2021 if (!timer->
addTimer(1, 1000, now+50000, now+10000000)) {
2026 if (!timer->
addTimer(2, 2000, now+55000, now+15000000)) {
2031 if (!timer->
addTimer(3, 3000, now+60000, now+20000000)) {
2038 uint32 triggers = 0;
2039 double totalLatencyUs = 0;
2043 for (uint32 n = 0; n < 60; n++) {
2047 totalLatencyUs += (double)(now - time);
2048 unittest::detail(
"Timer %u triggered %.3f ms ago",
id, (now - time) / 1000.0);
2059 if (triggers == 0) {
2066 unittest::metric(
"avg_trigger_latency", totalLatencyUs / (
double)triggers,
"us",
false);
2083 if (pipe(inPipe) != 0) {
unittest::fail(
"pipe() failed");
return false; }
2084 pid_t child = fork();
2085 if (child < 0) {
unittest::fail(
"fork() failed"); close(inPipe[0]); close(inPipe[1]);
return false; }
2087 dup2(inPipe[0], STDIN_FILENO);
2088 close(inPipe[0]); close(inPipe[1]);
2089 execl(
"/bin/sh",
"sh",
"-c",
"read x", (
char*)NULL);
2093 uint32 pid = (uint32)child;
2095 bool detected =
false;
2096 for (
int i = 0; i < 40 && !detected; i++) {
2097 if (!
ProbeProcessWait(pid, info)) {
unittest::fail(
"ProbeProcessWait returned false"); kill(child, SIGKILL); close(inPipe[1]); waitpid(child, NULL, 0);
return false; }
2102 unittest::fail(
"stdin-blocked child not detected (alive=%d waitingStdin=%d waitExact=%d)",
2104 kill(child, SIGKILL); close(inPipe[1]); waitpid(child, NULL, 0);
return false;
2106#if defined(__linux__)
2107 if (!info.
waitExact) {
unittest::fail(
"Linux should report waitExact"); kill(child, SIGKILL); close(inPipe[1]); waitpid(child, NULL, 0);
return false; }
2109 kill(child, SIGKILL);
2111 waitpid(child, NULL, 0);
2113 unittest::progress(55,
"spawn CPU-busy child, expect no stdin-wait + growing cpuTimeMs");
2114 uint32 pid2 =
NewProcessEx(
"i=0; while [ $i -lt 100000000 ]; do i=$((i+1)); done",
2115 NULL, NULL, NULL,
true,
false,
true, SIGKILL,
true);
2116 if (!pid2) {
unittest::fail(
"NewProcessEx(busy loop) failed");
return false; }
2125 if (busyFlagged) {
unittest::fail(
"busy child wrongly flagged waitingStdin");
return false; }
2136 uint32 slotCount = 350;
2138 char* bitField =
new char[bitFieldSize];
2147 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: false", loc);
2153 unittest::fail(
"GetFirstFreeBitLoc failed: %u, expected: 0", loc);
2158 unittest::fail(
"GetFirstFreeBitLocN failed: %u, expected: 0", loc);
2172 unittest::fail(
"GetFirstFreeBitLoc 2 failed: %u, expected: 0", loc);
2177 unittest::fail(
"GetFirstFreeBitLocN 2 failed: %u, expected: 0", loc);
2184 unittest::fail(
"GetFirstFreeBitLocN 3 failed: %u, expected: 11", loc);
2189 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: 10", loc);
2208 unittest::fail(
"GetFirstFreeBitLoc 4 failed: %u, expected: 1", loc);
2213 unittest::fail(
"GetFirstFreeBitLocN 5 failed: %u, expected: 11", loc);
2218 unittest::fail(
"GetFirstFreeBitLocN 6 failed: %u, expected: 11", loc);
2223 unittest::fail(
"GetFirstFreeBitLocN 7 failed: %u, expected: 150", loc);
2228 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: 149", loc);
2242 unittest::fail(
"GetFirstFreeBitLoc 8 failed: %u, expected: 1", loc);
2247 unittest::fail(
"GetFirstFreeBitLocN 9 failed: %u, expected: 11", loc);
2252 unittest::fail(
"GetFirstFreeBitLocN 10 failed: %u, expected: 11", loc);
2257 unittest::fail(
"GetFirstFreeBitLocN 11 failed: %u, expected: 250", loc);
2262 unittest::fail(
"GetFirstFreeBitLocN 12 failed: %u, expected: false", loc);
2268 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: 249", loc);
2282 unittest::fail(
"GetFirstFreeBitLoc 13 failed: %u, expected: 1", loc);
2287 unittest::fail(
"GetFirstFreeBitLocN 14 failed: %u, expected: 11", loc);
2292 unittest::fail(
"GetFirstFreeBitLocN 15 failed: %u, expected: 11", loc);
2297 unittest::fail(
"GetFirstFreeBitLocN 16 failed: %u, expected: 11", loc);
2302 unittest::fail(
"GetFirstFreeBitLocN 17 failed: %u, expected: 250", loc);
2307 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: 249", loc);
2320 unittest::fail(
"GetFirstFreeBitLoc 18 failed: %u, expected: 1", loc);
2325 unittest::fail(
"GetFirstFreeBitLocN 19 failed: %u, expected: 11", loc);
2330 unittest::fail(
"GetFirstFreeBitLocN 20 failed: %u, expected: 11", loc);
2335 unittest::fail(
"GetFirstFreeBitLocN 21 failed: %u, expected: 250", loc);
2340 unittest::fail(
"GetFirstFreeBitLocN 22 failed: %u, expected: 250", loc);
2345 unittest::fail(
"GetFirstFreeBitLocN 23 failed: %u, expected: false", loc);
2350 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: 249", loc);
2377 hMapFile = CreateFileMapping(
2378 INVALID_HANDLE_VALUE,
2381 (uint32)((size >> 32) & 0xffffffff),
2382 (uint32)(size & 0xffffffff),
2393 bool alreadyExisted = (GetLastError() == ERROR_ALREADY_EXISTS);
2395 if (hMapFile == NULL) {
2401 pBuf = (
char*) MapViewOfFile(hMapFile,
2402 FILE_MAP_ALL_ACCESS,
2406 int error = GetLastError();
2407 CloseHandle(hMapFile);
2416 if (force && alreadyExisted)
2417 memset(pBuf, 0, (
size_t)size);
2422 (*SharedMemoryFileHandleMap)[pBuf] = hMapFile;
2431 int fd = open(memname, O_CREAT | O_RDWR, 0666);
2433 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't create shared memory: '%s' (err: %d)...", memname, errno);
2437 if (ftruncate(fd, size) == -1) {
2438 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't truncate shared memory: '%s' size: %u (%d) (err: %d)...", memname, size, fd, errno);
2443 char* pBuf = (
char*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
2444 if (pBuf == MAP_FAILED) {
2445 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't map created shared memory: '%s' (err: %d)...", memname, errno);
2452 (*SharedMemoryFileHandleMap)[pBuf] = std::string(memname);
2459 int fd = shm_open(memname, O_CREAT | O_RDWR, 0666);
2461 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't create shared memory: '%s' (err: %d)...", memname, errno);
2465 if (ftruncate(fd, size) == -1) {
2466 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't truncate shared memory: '%s' size: %u (%d) (err: %d)...", memname, size, fd, errno);
2471 char* pBuf = (
char*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
2472 if (pBuf == MAP_FAILED) {
2473 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't map created shared memory: '%s' (err: %d)...", memname, errno);
2480 (*SharedMemoryFileHandleMap)[pBuf] = memname;
2498 hMapFile = OpenFileMapping(
2499 FILE_MAP_ALL_ACCESS,
2503 if (hMapFile == NULL) {
2509 pBuf = (
char*) MapViewOfFile(hMapFile,
2510 FILE_MAP_ALL_ACCESS,
2517 CloseHandle(hMapFile);
2525 (*SharedMemoryFileHandleMap)[pBuf] = hMapFile;
2532 int fd = open(memname, O_RDWR);
2538 uint64 memSize = size;
2545 if (fstat(fd, &st) == -1 || st.st_size <= 0) {
2550 memSize = (uint64) st.st_size;
2552 pBuf = (
char*)mmap(NULL, memSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
2553 if (pBuf == MAP_FAILED) {
2560 (*SharedMemoryFileHandleMap)[pBuf] = std::string(memname);
2567 int fd = shm_open(memname, O_RDWR, 0666);
2573 uint64 memSize = size;
2579 if (fstat(fd, &st) == -1 || st.st_size <= 0) {
2580 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't stat opened shared memory: '%s' (err: %d)...", memname, errno);
2585 memSize = (uint64) st.st_size;
2587 pBuf = (
char*)mmap(NULL, memSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
2588 if (pBuf == MAP_FAILED) {
2595 (*SharedMemoryFileHandleMap)[pBuf] = memname;
2608 UnmapViewOfFile(data);
2644 const char* p = name;
2645 while ((p = strstr(p, portstr)) != NULL) {
2646 bool leftOK = (p == name) || !isdigit((
unsigned char)*(p - 1));
2647 char after = *(p + plen);
2648 bool rightOK = (after ==
'\0') || !isdigit((
unsigned char)after);
2649 if (leftOK && rightOK)
2656static uint32
ClearSegmentsIn(
const char* dir,
const char* prefix,
const char* portstr,
size_t plen) {
2660 size_t preflen = strlen(prefix);
2662 while ((e =
readdir(d)) != NULL) {
2663 if (strncmp(e->
d_name, prefix, preflen) != 0)
2667 std::string path = std::string(dir) +
"/" + e->
d_name;
2668 if (unlink(path.c_str()) == 0)
2683 snprintf(portstr,
sizeof(portstr),
"%u", port);
2684 size_t plen = strlen(portstr);
2690 count +=
ClearSegmentsIn(
"/dev/shm",
"sem.Semaphore_", portstr, plen);
2693 LogPrint(0,
LOG_SYSTEM, 1,
"Cleared %u stale shared segment(s) for port %u...", count, port);
2704 uint8 *data = (uint8*)&rval;
2705 data[0] = (uint8)(*input >> 56);
2706 data[1] = (uint8)(*input >> 48);
2707 data[2] = (uint8)(*input >> 40);
2708 data[3] = (uint8)(*input >> 32);
2709 data[4] = (uint8)(*input >> 24);
2710 data[5] = (uint8)(*input >> 16);
2711 data[6] = (uint8)(*input >> 8);
2712 data[7] = (uint8)(*input >> 0);
2724 return ((bitsize + 31) >> 5) << 2;
2728 memset(bitfield, 255, bytesize);
2734 uint32* data = (uint32*)bitfield;
2735 uint32* src = (uint32*)data;
2747 const int32 words = (int32)(bytesize >> 2);
2748 while (src - data < words && *src == 0)
2750 if (src - data >= words)
2753 _BitScanForward((DWORD*)&index, *src);
2755 index = ffsl(*src) - 1;
2757 index = ffsl(*src) - 1;
2760 loc = ((uint32)(src-data)*32) + index;
2766 uint32* data = (uint32*)bitfield;
2767 uint32* src = (uint32*)data;
2773 uint32 foundBlock = 0;
2776 const int32 words = (int32)(bytesize >> 2);
2778 while (src - data < words && *src == 0)
2780 if (src - data >= words)
2783 _BitScanForward((DWORD*)&index, *src);
2785 index = ffsl(*src) - 1;
2787 index = ffsl(*src) - 1;
2789 loc = ((uint32)(src - data) * 32) + index;
2802 if ((l >> 5) >= (bytesize >> 2))
2805 uint32* word = (uint32*)bitfield + (l >> 5);
2808 val = (_bittest((
long*)word, n) != 0);
2810 val = (bit)((*word & (
static_cast<uint32
>(1) << n)) != 0);
2812 val = (bit)((*word & (
static_cast<uint32
>(1) << n)) != 0);
2820 if (foundBlock >= num)
2822 if (index % 32 == 0) {
2827 while ((num - foundBlock > 31) && (src - data < words) && (*src ==
MAXVALUINT32)) {
2832 if (src - data >= words)
2834 if ((num - foundBlock > 15) && (*(uint16*)src ==
MAXVALUINT16)) {
2838 if ((num - foundBlock > 7) && (*((
unsigned char*)src+2) == 255)) {
2844 else if ((num - foundBlock > 7) && (*(
unsigned char*)src == 255)) {
2850 if (foundBlock >= num)
2857 if (index % 32 == 0)
2863 if ((l >> 5) >= (bytesize >> 2))
2866 uint32* word = (uint32*)bitfield + (l >> 5);
2869 val = (_bittest((
long*)word, n) != 0);
2871 val = (bit)((*word & (
static_cast<uint32
>(1) << n)) != 0);
2873 val = (bit)((*word & (
static_cast<uint32
>(1) << n)) != 0);
2878 src += (uint32)(index / 32);
2879 if (src - data >= words)
2888bool SetBit(uint32 loc, bit value,
char* bitfield, uint32 bytesize) {
2889 if ((loc + 7) >> 3 > bytesize)
2891 uint32* data = (uint32*)bitfield;
2892 uint32* src = (uint32*)data;
2901 _bittestandset((
long*)src, n);
2903 _bittestandreset((
long*)src, n);
2920bool SetBitN(uint32 loc, uint32 num, bit value,
char* bitfield, uint32 bytesize) {
2921 if ((loc + 7) >> 3 > bytesize)
2923 uint32* data = (uint32*)bitfield;
2924 uint32* src = (uint32*)data;
2931 for (uint32 i = 0; i < num; i++) {
2933 while (num - i > 31) {
2943 *((
unsigned char*)src + 2) = (value ? 255 : 0);
2948 else if (num - i > 7) {
2949 *(
unsigned char*)src = (value ? 255 : 0);
2958 _bittestandset((
long*)src, n);
2960 _bittestandreset((
long*)src, n);
2983bool GetBit(uint32 loc,
const char* bitfield, uint32 bytesize, bit& val) {
2984 if ((loc + 7) >> 3 > bytesize)
2986 uint32* data = (uint32*)bitfield;
2987 uint32* src = (uint32*)data;
2995 val = (_bittest((
long*)src, n) != 0);
2997 uint32 mask =
static_cast<uint32
>( 1 << n ) ;
2998 val = (bit)(mask & *src);
3000 uint32 mask =
static_cast<uint32
>(1 << n);
3001 val = (bit)(mask & *src);
3009 uint32* data = (uint32*)bitfield;
3010 uint32* src = (uint32*)(bitfield + bytesize - 4);
3014 while ((*src == 0xFFFFFFFF)) {
3021 _BitScanReverse((DWORD*)&index, ~(*src));
3023 index = 31 - __builtin_clz(~(*src));
3025 index = 31 - __builtin_clz(~(*src));
3027 loc = ((uint32)(src - data) * 32) + index;
3035 str.reserve(bytesize * 9);
3038 for(i = 0; i < bytesize; i++) {
3039 for(j = 0; j < 8; j++) {
3041 str.push_back((bitfield[i] & (1 << j)) ?
'_' :
'0');
3054 uint32 strSize = (uint32)str.size();
3059 return StringFormat(
"%s [%u]: %s\n", title, size, str.c_str());
3068 while (loc < strSize-1) {
3069 str2 += str.substr(loc, 36) +
"\n";
3073 str2 += str.substr(loc) +
"\n";
3083 return InterlockedIncrement((LONG*)&v);
3086 __sync_add_and_fetch(&v, 1);
3093 return InterlockedIncrement64((LONGLONG*)&v);
3096 __sync_add_and_fetch(&v, 1);
3103 return InterlockedDecrement((LONG*)&v);
3106 __sync_add_and_fetch(&v, -1);
3113 return InterlockedDecrement64((LONGLONG*)&v);
3116 __sync_add_and_fetch(&v, -1);
3132 std::string tracePrint;
3135 std::list<std::string>::iterator i = trace.begin(), e = trace.end();
3139 if ((++line > startLine) && (!endLine || (line <= endLine)))
3140 tracePrint +=
" -" + (*i) +
"\n";
3147 std::list<std::string> trace;
3176 size = backtrace(array, 200);
3177 strings = backtrace_symbols(array, size);
3178 for (i = 0; i < size; i++)
3179 trace.push_back(strings[i]);
3194 (LPTHREAD_START_ROUTINE) func,
3199 if (thread != NULL) {
3200 osID = ::GetThreadId(thread);
3207 pthread_attr_t attr;
3208 pthread_attr_init(&attr);
3210 pthread_attr_setschedpolicy(&attr, SCHED_RR);
3211 pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
3215 if ((res=pthread_create(&thread, &attr, func, args)) != 0)
3218 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
3219 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
3222 pthread_threadid_np(thread, &tid);
3225 osID = (uint32) thread;
3235 int res = WaitForSingleObject(hThread, 0);
3236 if (res != WAIT_OBJECT_0)
3249 return (pthread_kill(hThread, 0) != 0);
3262 return (pthread_kill(hThread, 0) != 0);
3275 CloseHandle(hThread);
3277 pthread_join(hThread, NULL);
3294 if (WaitForSingleObject(hThread, 0) != WAIT_OBJECT_0)
3296 CloseHandle(hThread);
3297 #elif defined __APPLE__
3298 if (pthread_kill(hThread, 0) == 0)
3300 pthread_join(hThread, NULL);
3302 if (pthread_tryjoin_np(hThread, NULL) != 0)
3313 int res = WaitForSingleObject(hThread, timeoutMS ? timeoutMS : INFINITE);
3314 if(res != WAIT_OBJECT_0)
3324 return (pthread_join(hThread, NULL) == 0);
3332 while (pthread_kill(hThread, 0) == 0) {
3333 if (waited >= timeoutMS)
3339 pthread_join(hThread, NULL);
3345 if (pthread_timedjoin_np(hThread, NULL, &ts) != 0)
3351 if (pthread_join(hThread, NULL) != 0)
3368 char* msg =
new char[2048];
3369 int length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
3370 NULL, GetLastError(), 0, msg,
sizeof(msg), NULL);
3376 CloseHandle(hThread);
3382 pthread_cancel(hThread);
3383 if (pthread_join(hThread, NULL) != 0)
3401 sigaddset(set, SIGINT);
3402 sigaddset(set, SIGTERM);
3403 sigaddset(set, SIGHUP);
3404 sigaddset(set, SIGUSR2);
3418 if (sigwait(&set, &sig) != 0)
3441 return (pthread_sigmask(SIG_BLOCK, &set, NULL) == 0);
3460 pthread_sigmask(SIG_BLOCK, &set, NULL);
3486 return (SuspendThread(hThread) >= 0);
3488 return (pthread_kill(hThread, SIGSTOP) == 0);
3496 while ( (count = ResumeThread(hThread)) > 1);
3497 return (count == 1);
3499 return (pthread_kill(hThread, SIGCONT) == 0);
3510 tid = ::GetCurrentThreadId();
3515 pthread_threadid_np(pthread_self(), &
id);
3518 tid = (uint32) pthread_self();
3526 tid = ::GetCurrentThreadId();
3531 if (pthread_threadid_np(pthread_self(), &
id) != 0)
3535 int id = syscall(SYS_gettid);
3549 thread = pthread_self();
3557 if (!GetExitCodeThread(hThread, &code))
3559 return (code == STILL_ACTIVE);
3572 return (pthread_kill(hThread, 0) == 0);
3579 return (pthread_kill(hThread, 0) == 0);
3588 #if defined RUSAGE_THREAD
3602 uint64 cpuTicks = 0;
3603 LARGE_INTEGER perfFreq;
3604 if (!QueryPerformanceFrequency(&perfFreq) || !perfFreq.QuadPart)
3606 if (!QueryThreadCycleTime(hThread, &cpuTicks))
3608 ticks = cpuTicks / (perfFreq.QuadPart / 1000000);
3621 mach_port_t machThread = pthread_mach_thread_np(hThread);
3622 if (machThread == MACH_PORT_NULL)
3624 thread_basic_info_data_t info;
3625 mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
3626 if (thread_info(machThread, THREAD_BASIC_INFO, (thread_info_t)&info, &infoCount) != KERN_SUCCESS)
3628 ticks = (uint64)info.user_time.seconds * 1000000 + info.user_time.microseconds
3629 + (uint64)info.system_time.seconds * 1000000 + info.system_time.microseconds;
3633 if (pthread_getcpuclockid(hThread, &cid) != 0)
3636 if (clock_gettime(cid, &ts) != -1 ) {
3637 ticks = ((uint64)ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
3652 uint64 cpuTicks = 0;
3653 LARGE_INTEGER perfFreq;
3654 if (!QueryPerformanceFrequency(&perfFreq) || !perfFreq.QuadPart)
3658 ticks = cpuTicks / (perfFreq.QuadPart / 1000000);
3670 if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != -1 ) {
3671 ticks = ((uint64)ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
3694 HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS,
FALSE, osProcID);
3700 uint64 cpuTicks = 0;
3701 LARGE_INTEGER perfFreq;
3702 if (!QueryPerformanceFrequency(&perfFreq) || !perfFreq.QuadPart)
3704 if (!QueryProcessCycleTime(hProcess, &cpuTicks))
3706 ticks = cpuTicks / (perfFreq.QuadPart / 1000000);
3719 if ((pid_t)osProcID != getpid())
3722 if (getrusage(RUSAGE_SELF, &ru) != 0)
3724 ticks = ((uint64)ru.ru_utime.tv_sec * 1000000) + (uint64)ru.ru_utime.tv_usec
3725 + ((uint64)ru.ru_stime.tv_sec * 1000000) + (uint64)ru.ru_stime.tv_usec;
3729 if (clock_getcpuclockid(osProcID, &clockid) != 0)
3732 if (clock_gettime(clockid, &ts) != -1 ) {
3733 ticks = ((uint64)ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
3761 uint64 cpuTicks = 0;
3762 LARGE_INTEGER perfFreq;
3763 if (!QueryPerformanceFrequency(&perfFreq) || !perfFreq.QuadPart)
3765 if (!QueryProcessCycleTime(::GetCurrentProcess(), &cpuTicks))
3767 ticks = cpuTicks / (perfFreq.QuadPart / 1000000);
3780 if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) != -1 ) {
3781 ticks = ((uint64)ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
3801bool GetProcAndOSCPUUsage(
double& procPercentUse,
double& osPercentUse, uint64 &prevOSTicks, uint64 &prevOSIdleTicks, uint64 &prevProcTicks) {
3803 return GetProcAndOSCPUUsage(0, procPercentUse, osPercentUse, prevOSTicks, prevOSIdleTicks, prevProcTicks);
3805 return GetProcAndOSCPUUsage(getpid(), procPercentUse, osPercentUse, prevOSTicks, prevOSIdleTicks, prevProcTicks);
3810bool GetProcAndOSCPUUsage(uint32 osProcID,
double& procPercentUse,
double& osPercentUse, uint64 &prevOSTicks, uint64 &prevOSIdleTicks, uint64 &prevProcTicks) {
3811 procPercentUse = osPercentUse = 0;
3813 uint64 totalTicks, kernelTicks, userTicks, idleTicks, procTotalTicks, procUserTicks, procKernelTicks;
3816 FILETIME idleTime, kernelTime, userTime;
3817 if (!GetSystemTimes(&idleTime, &kernelTime, &userTime))
3820 idleTicks = FileTimeToUint64(idleTime);
3821 kernelTicks = FileTimeToUint64(kernelTime);
3822 userTicks = FileTimeToUint64(userTime);
3823 totalTicks = kernelTicks + userTicks;
3825 FILETIME procCreationTime, procExitTime, procKernelTime, procUserTime;
3828 if (!GetProcessTimes(GetCurrentProcess(), &procCreationTime, &procExitTime, &procKernelTime, &procUserTime))
3832 HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS,
FALSE, osProcID);
3836 if (!GetProcessTimes(hProcess, &procCreationTime, &procExitTime, &procKernelTime, &procUserTime))
3840 procKernelTicks = FileTimeToUint64(procKernelTime);
3841 procUserTicks = FileTimeToUint64(procUserTime);
3842 procTotalTicks = procKernelTicks + procUserTicks;
3847 host_cpu_load_info_data_t cpuInfo;
3848 mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
3849 if (host_statistics64(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info64_t)&cpuInfo, &count) != KERN_SUCCESS)
3853 long ticksPerSec = sysconf(_SC_CLK_TCK);
3854 uint64 usPerTick = (ticksPerSec > 0) ? (1000000 / ticksPerSec) : 10000;
3855 totalTicks = ((uint64)cpuInfo.cpu_ticks[CPU_STATE_USER] + cpuInfo.cpu_ticks[CPU_STATE_SYSTEM] + cpuInfo.cpu_ticks[CPU_STATE_IDLE] + cpuInfo.cpu_ticks[CPU_STATE_NICE]) * usPerTick;
3856 idleTicks = (uint64)cpuInfo.cpu_ticks[CPU_STATE_IDLE] * usPerTick;
3857 if (osProcID == 0 || osProcID == (uint32)getpid()) {
3858 task_thread_times_info_data_t threadTimes;
3859 count = TASK_THREAD_TIMES_INFO_COUNT;
3860 if (task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t)&threadTimes, &count) == KERN_SUCCESS)
3861 procTotalTicks = (uint64)threadTimes.user_time.seconds * 1000000 + threadTimes.user_time.microseconds + (uint64)threadTimes.system_time.seconds * 1000000 + threadTimes.system_time.microseconds;
3869 std::string statLine, procStatLine;
3870 std::ifstream statFile (
"/proc/stat");
3871 std::ifstream procStatFile (
StringFormat(
"/proc/%d/stat", osProcID).c_str());
3872 if (statFile.is_open())
3873 getline (statFile, statLine);
3877 if (procStatFile.is_open())
3878 getline (procStatFile, procStatLine);
3882 if (!statLine.length() || !procStatLine.length())
3887 int retval = sscanf(statLine.c_str(),
"cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
3888 &fields[0], &fields[1], &fields[2], &fields[3], &fields[4],
3889 &fields[5], &fields[6], &fields[7], &fields[8], &fields[9]);
3891 for (
int i=0; i<10; i++)
3892 totalTicks += fields[i];
3893 idleTicks = fields[3];
3895 uint64 utime_ticks, stime_ticks, cutime_ticks, cstime_ticks;
3896 retval = sscanf(procStatLine.c_str(),
"%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu %llu %llu",
3897 &utime_ticks, &stime_ticks, &cutime_ticks, &cstime_ticks);
3899 procTotalTicks = utime_ticks + stime_ticks + cutime_ticks + cstime_ticks;
3902 uint64 totalTicksSinceLastTime = totalTicks - prevOSTicks;
3903 uint64 idleTicksSinceLastTime = idleTicks - prevOSIdleTicks;
3904 uint64 procTicksSinceLastTime = procTotalTicks - prevProcTicks;
3906 osPercentUse = 1.0f-((totalTicksSinceLastTime > 0) ? ((double)idleTicksSinceLastTime)/totalTicksSinceLastTime : 0);
3907 procPercentUse = ((totalTicksSinceLastTime > 0) ? ((double)procTicksSinceLastTime)/totalTicksSinceLastTime : 0);
3912 prevOSTicks = totalTicks;
3913 prevOSIdleTicks = idleTicks;
3914 prevProcTicks = procTotalTicks;
3922 static uint64 PreviousTotalTicks = 0;
3923 static uint64 PreviousIdleTicks = 0;
3925 uint64 totalTicks, kernelTicks, userTicks, idleTicks;
3929 FILETIME idleTime, kernelTime, userTime;
3930 if (!GetSystemTimes(&idleTime, &kernelTime, &userTime))
3933 idleTicks = FileTimeToUint64(idleTime);
3934 kernelTicks = FileTimeToUint64(kernelTime);
3935 userTicks = FileTimeToUint64(userTime);
3936 totalTicks = kernelTicks + userTicks;
3939 host_cpu_load_info_data_t cpuInfo;
3940 mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
3941 if (host_statistics64(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info64_t)&cpuInfo, &count) != KERN_SUCCESS)
3943 totalTicks = (uint64)cpuInfo.cpu_ticks[CPU_STATE_USER] + cpuInfo.cpu_ticks[CPU_STATE_SYSTEM] + cpuInfo.cpu_ticks[CPU_STATE_IDLE] + cpuInfo.cpu_ticks[CPU_STATE_NICE];
3944 idleTicks = (uint64)cpuInfo.cpu_ticks[CPU_STATE_IDLE];
3946 std::string statLine;
3947 std::ifstream statFile(
"/proc/stat");
3948 if (!statFile.is_open() || !getline(statFile, statLine) || !statLine.length())
3952 if (sscanf(statLine.c_str(),
"cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
3953 &fields[0], &fields[1], &fields[2], &fields[3], &fields[4],
3954 &fields[5], &fields[6], &fields[7], &fields[8], &fields[9]) < 10)
3957 for (
int i = 0; i < 10; i++)
3958 totalTicks += fields[i];
3959 idleTicks = fields[3];
3962 uint64 totalTicksSinceLastTime = totalTicks - PreviousTotalTicks;
3963 uint64 idleTicksSinceLastTime = idleTicks - PreviousIdleTicks;
3965 percentUse = 1.0f-((totalTicksSinceLastTime > 0) ? ((double)idleTicksSinceLastTime)/totalTicksSinceLastTime : 0);
3970 PreviousTotalTicks = totalTicks;
3971 PreviousIdleTicks = idleTicks;
3982 struct sched_param sched;
3985 policy = SCHED_OTHER;
3987 policy = sched_getscheduler(0);
3991 if (pthread_getschedparam(hThread, &policy, &sched) != 0)
4004 struct sched_param sched;
4005 memset(&sched, 0,
sizeof(
struct sched_param));
4007 policy = SCHED_FIFO;
4011 int res = pthread_setschedparam(hThread, policy, &sched);
4023 val = THREAD_PRIORITY_NORMAL;
4025 val = THREAD_PRIORITY_TIME_CRITICAL;
4027 val = THREAD_PRIORITY_HIGHEST;
4029 val = THREAD_PRIORITY_ABOVE_NORMAL;
4031 val = THREAD_PRIORITY_NORMAL;
4033 val = THREAD_PRIORITY_BELOW_NORMAL;
4035 val = THREAD_PRIORITY_LOWEST;
4037 val = THREAD_PRIORITY_IDLE;
4070 case THREAD_PRIORITY_TIME_CRITICAL:
4072 case THREAD_PRIORITY_HIGHEST:
4074 case THREAD_PRIORITY_ABOVE_NORMAL:
4076 case THREAD_PRIORITY_NORMAL:
4078 case THREAD_PRIORITY_BELOW_NORMAL:
4080 case THREAD_PRIORITY_LOWEST:
4111 const HWND hDesktop = GetDesktopWindow();
4113 if (!GetWindowRect(hDesktop, &desktop))
4118 width = (uint32)desktop.right;
4119 height = (uint32)desktop.bottom;
4130 char* oldName =
new char[1024];
4131 if (!GetConsoleTitle(oldName, 1024)) {
4135 char* newName =
StringFormat(size,
"%s - %s", name, oldName);
4136 bool res = (SetConsoleTitle(name) != 0);
4142 return (SetConsoleTitle(name) != 0);
4150 char* consoleName =
new char[1024];
4151 if (!GetConsoleTitle(consoleName, 1024)) {
4152 delete [] consoleName;
4155 HWND handle = FindWindow(NULL, consoleName);
4157 delete [] consoleName;
4161 if (!GetWindowRect(handle, &wRect)) {
4162 delete [] consoleName;
4166 int conX = (x<0) ? wRect.left : x;
4167 int conY = (y<0) ? wRect.top : y;
4168 int conW = (w<0) ? wRect.right - wRect.left : w;
4169 int conH = (h<0) ? wRect.bottom - wRect.top : h;
4171 bool res = (MoveWindow(handle, conX, conY, conW, conH,
true) != 0);
4172 delete [] consoleName;
4187 return (uint32)GetCurrentProcessId();
4189 return (uint32)getpid();
4194int RunOSCommand(
const char* cmdline,
const char* initdir, uint32 timeout, std::string& stdoutString, std::string& stderrString) {
4195 if (!cmdline || !strlen(cmdline))
4199 HANDLE g_hChildStd_OUT_Rd = NULL;
4200 HANDLE g_hChildStd_OUT_Wr = NULL;
4201 HANDLE g_hChildStd_ERR_Rd = NULL;
4202 HANDLE g_hChildStd_ERR_Wr = NULL;
4204 SECURITY_ATTRIBUTES sa;
4206 sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
4207 sa.bInheritHandle =
TRUE;
4208 sa.lpSecurityDescriptor = NULL;
4210 if ( ! CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &sa, 0) ) {
4214 if ( ! SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0) ){
4218 if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &sa, 0) ) {
4222 if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) ){
4225 PROCESS_INFORMATION piProcInfo;
4226 STARTUPINFO siStartInfo;
4227 bool bSuccess =
FALSE;
4230 ZeroMemory( &piProcInfo,
sizeof(PROCESS_INFORMATION) );
4234 ZeroMemory( &siStartInfo,
sizeof(STARTUPINFO) );
4235 siStartInfo.cb =
sizeof(STARTUPINFO);
4236 siStartInfo.hStdError = g_hChildStd_ERR_Wr;
4237 siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
4238 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
4244 bSuccess = (CreateProcess(NULL,
4254 CloseHandle(g_hChildStd_ERR_Wr);
4255 CloseHandle(g_hChildStd_OUT_Wr);
4267 bSuccess=(ReadFile( g_hChildStd_OUT_Rd, chBuf,
PROCBUFSIZE, &dwRead, NULL) != 0);
4268 if( ! bSuccess || dwRead == 0 )
break;
4269 std::string s(chBuf, dwRead);
4275 bSuccess=(ReadFile( g_hChildStd_ERR_Rd, chBuf,
PROCBUFSIZE, &dwRead, NULL) != 0);
4276 if( ! bSuccess || dwRead == 0 )
break;
4277 std::string s(chBuf, dwRead);
4284 if (GetExitCodeProcess(piProcInfo.hProcess, &exitcode) && (exitcode == STILL_ACTIVE)) {
4285 TerminateProcess(piProcInfo.hProcess, 1);
4287 CloseHandle(g_hChildStd_ERR_Rd);
4288 CloseHandle(g_hChildStd_OUT_Rd);
4289 CloseHandle(piProcInfo.hProcess);
4290 CloseHandle(piProcInfo.hThread);
4295 FILE* runfile = popen(cmdline,
"r");
4296 if (runfile == NULL)
4303 char* buffer =
new char[size+1];
4305 res = fread(buffer, 1, size, runfile);
4307 status = pclose(runfile);
4308 exitcode = WEXITSTATUS(status);
4314 stdoutString += buffer;
4315 }
while (res = fread(buffer, 1, size, runfile));
4317 status = pclose(runfile);
4318 exitcode = WEXITSTATUS(status);
4387uint32
NewProcess(
const char* cmdline,
const char* initdir,
const char* title, int16 x, int16 y, int16 w, int16 h) {
4389 if (!cmdline || !strlen(cmdline))
4396 ghJob = CreateJobObject(NULL, NULL);
4398 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
4400 jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
4401 SetInformationJobObject(ghJob, JobObjectExtendedLimitInformation, &jeli,
sizeof(jeli));
4407 ZeroMemory(&(pData->procInfo),
sizeof(pData->procInfo));
4408 ZeroMemory(&(pData->si),
sizeof(pData->si));
4409 pData->si.cb =
sizeof(pData->si);
4410 pData->si.wShowWindow = SW_SHOWNOACTIVATE;
4412 if ( (x>=0) && (y>=0) && (w>=0) && (h>=0) ) {
4413 pData->si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USEPOSITION | STARTF_USESIZE;
4416 pData->si.dwXSize = w;
4417 pData->si.dwYSize = h;
4420 pData->si.dwFlags = STARTF_USESHOWWINDOW;
4425 char* titleCopy = NULL;
4427 size_t tlen = strlen(title);
4428 titleCopy =
new char[tlen + 1];
4429 memcpy(titleCopy, title, tlen + 1);
4430 pData->si.lpTitle = titleCopy;
4433 size_t clen = strlen(cmdline);
4434 char* cmd =
new char[clen + 1];
4435 memcpy(cmd, cmdline, clen + 1);
4439 int res = CreateProcess(NULL, cmd, NULL, NULL,
TRUE, CREATE_NEW_CONSOLE, NULL, initdir, &pData->si, &pData->procInfo);
4440 delete [] titleCopy;
4443 char* msg =
new char[2048];
4444 int length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
4445 NULL, GetLastError(), 0, msg,
sizeof(msg), NULL);
4454 AssignProcessToJobObject(ghJob, pData->procInfo.hProcess);
4457 return pData->procInfo.dwProcessId;
4477 pid_t ppid_before_fork = getpid();
4485 else if (pid == 0) {
4487 if ( initdir && (chdir(initdir) != 0) ) {
4488 LogPrint(0,
LOG_SYSTEM,0,
"Could not run process '%s' from starup dir '%s'\n", cmdline, initdir);
4493 int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
4494 if (r == -1) { perror(0); exit(1); }
4497 if (getppid() != ppid_before_fork)
4501 execvp(argv[0],argv);
4526 if (GetExitCodeProcess(pData->procInfo.hProcess, &exitcode) && (exitcode == STILL_ACTIVE)) {
4531 CloseHandle(pData->procInfo.hProcess);
4532 CloseHandle(pData->procInfo.hThread);
4533 if (pData->hOutRead) CloseHandle(pData->hOutRead);
4534 if (pData->hErrRead) CloseHandle(pData->hErrRead);
4535 if (pData->hInWrite) CloseHandle(pData->hInWrite);
4536 if (pData->hJob) CloseHandle(pData->hJob);
4538 returncode = exitcode;
4544 HANDLE hproc = OpenProcess(NULL,
false, (DWORD)proc);
4547 if (GetExitCodeProcess(hproc, &exitcode) && (exitcode == STILL_ACTIVE)) {
4558 int res = waitpid(proc, &status, WNOHANG);
4570 returncode = WEXITSTATUS(status);
4574 else if (res == 0) {
4581#if !defined(WINDOWS)
4609 TerminateProcess(pData->procInfo.hProcess, 1);
4610 CloseHandle(pData->procInfo.hProcess);
4611 CloseHandle(pData->procInfo.hThread);
4612 if (pData->hOutRead) CloseHandle(pData->hOutRead);
4613 if (pData->hErrRead) CloseHandle(pData->hErrRead);
4614 if (pData->hInWrite) CloseHandle(pData->hInWrite);
4615 if (pData->hJob) CloseHandle(pData->hJob);
4621 HANDLE hproc = OpenProcess(NULL, NULL, (DWORD)proc);
4624 if (TerminateProcess(hproc, 1) == 0) {
4634 bool ok = (kill(proc, SIGKILL) == 0);
4675 out.alive =
false; out.waitExact =
false; out.waitingStdin =
false; out.cpuTimeMs = 0;
4676 if (!pid)
return false;
4677 HANDLE h = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
FALSE, (DWORD)pid);
4678 if (!h)
return true;
4680 if (GetExitCodeProcess(h, &code) && code == STILL_ACTIVE)
4684 bool haveTreeCpu =
false;
4685 ProcessData* pd = NULL;
4690 if (pd && pd->hJob) {
4691 JOBOBJECT_BASIC_ACCOUNTING_INFORMATION jbai;
4692 ZeroMemory(&jbai,
sizeof(jbai));
4694 if (QueryInformationJobObject(pd->hJob, JobObjectBasicAccountingInformation,
4695 &jbai,
sizeof(jbai), &retLen)) {
4699 out.cpuTimeMs = (uint64)((jbai.TotalUserTime.QuadPart +
4700 jbai.TotalKernelTime.QuadPart) / 10000ULL);
4705 FILETIME ct, et, kt, ut;
4706 if (GetProcessTimes(h, &ct, &et, &kt, &ut)) {
4707 ULARGE_INTEGER k, u;
4708 k.LowPart = kt.dwLowDateTime; k.HighPart = kt.dwHighDateTime;
4709 u.LowPart = ut.dwLowDateTime; u.HighPart = ut.dwHighDateTime;
4710 out.cpuTimeMs = (uint64)((k.QuadPart + u.QuadPart) / 10000ULL);
4732 uint64 firstCpu = out.cpuTimeMs;
4734 uint64 secondCpu = firstCpu;
4735 if (pd && pd->hJob) {
4736 JOBOBJECT_BASIC_ACCOUNTING_INFORMATION j2;
4737 ZeroMemory(&j2,
sizeof(j2));
4739 if (QueryInformationJobObject(pd->hJob, JobObjectBasicAccountingInformation,
4740 &j2,
sizeof(j2), &rl))
4741 secondCpu = (uint64)((j2.TotalUserTime.QuadPart +
4742 j2.TotalKernelTime.QuadPart) / 10000ULL);
4744 FILETIME c2, e2, k2, u2;
4745 if (GetProcessTimes(h, &c2, &e2, &k2, &u2)) {
4746 ULARGE_INTEGER k, u;
4747 k.LowPart = k2.dwLowDateTime; k.HighPart = k2.dwHighDateTime;
4748 u.LowPart = u2.dwLowDateTime; u.HighPart = u2.dwHighDateTime;
4749 secondCpu = (uint64)((k.QuadPart + u.QuadPart) / 10000ULL);
4753 out.cpuTimeMs = secondCpu;
4759 out.waitingStdin = (secondCpu == firstCpu);
4764#elif defined(__APPLE__)
4769 out.alive =
false; out.waitExact =
false; out.waitingStdin =
false; out.cpuTimeMs = 0;
4770 if (!pid)
return false;
4771 if (kill((pid_t)pid, 0) != 0 && errno == ESRCH)
return true;
4773 struct proc_taskinfo ti;
4774 if (proc_pidinfo((
int)pid, PROC_PIDTASKINFO, 0, &ti,
sizeof(ti)) == (
int)
sizeof(ti))
4775 out.cpuTimeMs = (uint64)((ti.pti_total_user + ti.pti_total_system) / 1000000ULL);
4777 int n = proc_pidinfo((
int)pid, PROC_PIDLISTTHREADS, 0, tids,
sizeof(tids));
4778 if (n <= 0)
return true;
4779 int count = n / (int)
sizeof(uint64_t);
4780 bool allWaiting = (count > 0);
4781 for (
int i = 0; i < count; i++) {
4782 struct proc_threadinfo th;
4783 if (proc_pidinfo((
int)pid, PROC_PIDTHREADINFO, tids[i], &th,
sizeof(th)) != (
int)
sizeof(th)
4784 || th.pth_run_state != TH_STATE_WAITING) {
4785 allWaiting =
false;
break;
4789 struct pipe_fdinfo pfd;
4790 if (proc_pidfdinfo((
int)pid, 0, PROC_PIDFDPIPEINFO, &pfd,
sizeof(pfd)) == (
int)
sizeof(pfd))
4791 out.waitingStdin =
true;
4800#if defined(__x86_64__)
4801 static const long PPW_SYS_read = 0;
4802#elif defined(__aarch64__)
4803 static const long PPW_SYS_read = 63;
4805 static const long PPW_SYS_read = -1;
4808 static bool ppwReadStat(
const char* path,
char& state,
long& pgrp, uint64& cpuTicks) {
4809 FILE* f = fopen(path,
"r");
4810 if (!f)
return false;
4812 size_t len = fread(buf, 1,
sizeof(buf) - 1, f);
4814 if (!len)
return false;
4816 const char* p = strrchr(buf,
')');
4817 if (!p)
return false;
4819 long ppid = 0;
unsigned long ut = 0, st = 0;
4822 if (sscanf(p,
" %c %ld %ld %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu",
4823 &st_c, &ppid, &pgrp, &ut, &st) != 5)
4826 cpuTicks = (uint64)ut + (uint64)st;
4831 static int ppwSyscallIsStdinRead(
const char* path) {
4832 FILE* f = fopen(path,
"r");
4835 size_t len = fread(buf, 1,
sizeof(buf) - 1, f);
4837 if (!len)
return -1;
4839 long nr = 0;
unsigned long arg0 = 0;
4840 if (sscanf(buf,
"%ld %lx", &nr, &arg0) < 1)
4842 if (PPW_SYS_read < 0)
return -1;
4843 return (nr == PPW_SYS_read && arg0 == 0) ? 1 : 0;
4849 if (!pid)
return false;
4851 snprintf(path,
sizeof(path),
"/proc/%u/stat", pid);
4852 char state = 0;
long pgid = 0; uint64 ticks = 0;
4853 if (!ppwReadStat(path, state, pgid, ticks))
return true;
4854 if (state ==
'Z' || state ==
'X')
return true;
4856 long tck = sysconf(_SC_CLK_TCK);
4857 if (tck <= 0) tck = 100;
4858 uint64 totalTicks = 0;
4859 bool sawUnreadable =
false, sawStdinRead =
false;
4865 while ((de =
readdir(proc)) != NULL) {
4866 if (de->
d_name[0] <
'0' || de->
d_name[0] >
'9')
continue;
4867 unsigned long p = strtoul(de->
d_name, NULL, 10);
4868 char pstate = 0;
long ppgrp = 0; uint64 pticks = 0;
4869 snprintf(path,
sizeof(path),
"/proc/%lu/stat", p);
4870 if (!ppwReadStat(path, pstate, ppgrp, pticks))
continue;
4871 if (ppgrp != pgid && (uint32)p != pid)
continue;
4872 totalTicks += pticks;
4875 snprintf(tdir,
sizeof(tdir),
"/proc/%lu/task", p);
4877 if (!tasks) { sawUnreadable =
true;
continue; }
4879 while ((te =
readdir(tasks)) != NULL) {
4880 if (te->
d_name[0] <
'0' || te->
d_name[0] >
'9')
continue;
4881 char tpath[352];
char tstate = 0;
long tpgrp = 0; uint64 tt = 0;
4882 snprintf(tpath,
sizeof(tpath),
"%s/%s/stat", tdir, te->
d_name);
4883 if (ppwReadStat(tpath, tstate, tpgrp, tt) && tstate !=
'S')
4885 snprintf(tpath,
sizeof(tpath),
"%s/%s/syscall", tdir, te->
d_name);
4886 int r = ppwSyscallIsStdinRead(tpath);
4887 if (r < 0) sawUnreadable =
true;
4888 else if (r == 1) sawStdinRead =
true;
4893 }
else sawUnreadable =
true;
4894 out.
cpuTimeMs = totalTicks * 1000ULL / (uint64)tck;
4896 else if (!sawUnreadable) out.
waitExact =
true;
4914 const std::map<std::string, std::string>*
env;
4929 pid_t ppid_before_fork = getpid();
4930 (void)ppid_before_fork;
4932 const char* shArgv[4] = {
"sh",
"-c", r.
cmdline, NULL };
4945 int devnull = open(
"/dev/null", O_WRONLY);
4947 dup2(devnull, STDOUT_FILENO);
4948 dup2(devnull, STDERR_FILENO);
4963 std::map<std::string, std::string>::const_iterator ei = r.
env->begin();
4964 while (ei != r.
env->end()) { setenv(ei->first.c_str(), ei->second.c_str(), 1); ei++; }
4973 if (getppid() != ppid_before_fork)
4975 pid_t self = getpid();
4976 pid_t nanny = fork();
4983 EV_SET(&ev, ppid_before_fork, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, NULL);
4984 if (kevent(kq, &ev, 1, NULL, 0, NULL) != -1) {
4986 kevent(kq, NULL, 0, &out, 1, NULL);
4989 kill(-self, SIGKILL);
4996 if (pres == -1) { perror(0); _exit(1); }
4998 if (getppid() != ppid_before_fork)
5021static std::condition_variable&
gLaunchCv = *
new std::condition_variable;
5027 std::unique_lock<std::mutex> lock(
gLaunchMx);
5042 std::unique_lock<std::mutex> lock(
gLaunchMx);
5059uint32
NewProcessEx(
const char* cmdline,
const char* initdir,
const char* title,
5060 const std::map<std::string, std::string>* env,
5061 bool captureOutput,
bool ignoreOutput,
bool newProcessGroup,
5062 int posixParentDeathSig,
bool posixUseShell) {
5063 if (!cmdline || !strlen(cmdline))
5068 (void)posixParentDeathSig; (void)posixUseShell;
5071 ghJob = CreateJobObject(NULL, NULL);
5073 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
5074 jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
5075 SetInformationJobObject(ghJob, JobObjectExtendedLimitInformation, &jeli,
sizeof(jeli));
5080 ZeroMemory(&(pData->procInfo),
sizeof(pData->procInfo));
5081 ZeroMemory(&(pData->si),
sizeof(pData->si));
5082 pData->si.cb =
sizeof(pData->si);
5083 pData->si.wShowWindow = SW_SHOWNOACTIVATE;
5084 pData->si.dwFlags = STARTF_USESHOWWINDOW;
5088 HANDLE hOutWrite = NULL, hErrWrite = NULL, hNull = NULL, hInRead = NULL;
5089 SECURITY_ATTRIBUTES sa;
5090 ZeroMemory(&sa,
sizeof(sa));
5091 sa.nLength =
sizeof(sa);
5092 sa.bInheritHandle =
TRUE;
5093 sa.lpSecurityDescriptor = NULL;
5095 if (captureOutput) {
5097 if ( !CreatePipe(&pData->hOutRead, &hOutWrite, &sa, 0) ||
5098 !CreatePipe(&pData->hErrRead, &hErrWrite, &sa, 0) ) {
5099 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessEx: could not create output pipes for '%s'", cmdline);
5100 if (pData->hOutRead) CloseHandle(pData->hOutRead);
5101 if (hOutWrite) CloseHandle(hOutWrite);
5102 if (pData->hErrRead) CloseHandle(pData->hErrRead);
5106 SetHandleInformation(pData->hOutRead, HANDLE_FLAG_INHERIT, 0);
5107 SetHandleInformation(pData->hErrRead, HANDLE_FLAG_INHERIT, 0);
5116 if (!CreatePipe(&hInRead, &pData->hInWrite, &sa, 0)) {
5117 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessEx: could not create stdin pipe for '%s'", cmdline);
5118 CloseHandle(pData->hOutRead); CloseHandle(hOutWrite);
5119 CloseHandle(pData->hErrRead); CloseHandle(hErrWrite);
5123 SetHandleInformation(pData->hInWrite, HANDLE_FLAG_INHERIT, 0);
5124 pData->si.dwFlags |= STARTF_USESTDHANDLES;
5125 pData->si.hStdOutput = hOutWrite;
5126 pData->si.hStdError = hErrWrite;
5127 pData->si.hStdInput = hInRead;
5129 else if (ignoreOutput) {
5130 hNull = CreateFile(
"NUL", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
5131 &sa, OPEN_EXISTING, 0, NULL);
5132 if (hNull != INVALID_HANDLE_VALUE) {
5133 pData->si.dwFlags |= STARTF_USESTDHANDLES;
5134 pData->si.hStdOutput = hNull;
5135 pData->si.hStdError = hNull;
5136 pData->si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
5142 char* envBlock = NULL;
5143 if (env && env->size()) {
5144 std::map<std::string, std::string> merged;
5145 LPCH parentEnv = GetEnvironmentStrings();
5147 for (LPCH p = parentEnv; *p; ) {
5148 std::string entry = p;
5149 size_t eq = entry.find(
'=');
5150 if (eq != std::string::npos && eq > 0)
5151 merged[entry.substr(0, eq)] = entry.substr(eq + 1);
5152 p += entry.size() + 1;
5154 FreeEnvironmentStrings(parentEnv);
5156 std::map<std::string, std::string>::const_iterator ei = env->begin();
5157 while (ei != env->end()) { merged[ei->first] = ei->second; ei++; }
5159 std::map<std::string, std::string>::iterator mi = merged.begin();
5160 while (mi != merged.end()) { total += mi->first.size() + 1 + mi->second.size() + 1; mi++; }
5161 envBlock =
new char[total];
5163 for (mi = merged.begin(); mi != merged.end(); mi++) {
5164 std::string kv = mi->first +
"=" + mi->second;
5165 memcpy(envBlock + off, kv.c_str(), kv.size() + 1);
5166 off += kv.size() + 1;
5171 DWORD flags = CREATE_NEW_CONSOLE;
5172 if (newProcessGroup)
5173 flags |= CREATE_NEW_PROCESS_GROUP;
5180 char* titleCopy = NULL;
5182 size_t tlen = strlen(title);
5183 titleCopy =
new char[tlen + 1];
5184 memcpy(titleCopy, title, tlen + 1);
5185 pData->si.lpTitle = titleCopy;
5187 size_t clen = strlen(cmdline);
5188 char* cmd =
new char[clen + 1];
5189 memcpy(cmd, cmdline, clen + 1);
5191 int res = CreateProcess(NULL, cmd, NULL, NULL,
TRUE, flags, envBlock, initdir, &pData->si, &pData->procInfo);
5193 delete [] titleCopy;
5195 if (envBlock)
delete [] envBlock;
5200 if (hOutWrite) CloseHandle(hOutWrite);
5201 if (hErrWrite) CloseHandle(hErrWrite);
5202 if (hInRead) CloseHandle(hInRead);
5203 if (hNull) CloseHandle(hNull);
5207 int length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, msg,
sizeof(msg), NULL);
5209 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessEx: error creating process: %s\n%s", msg, cmdline);
5210 if (pData->hOutRead) CloseHandle(pData->hOutRead);
5211 if (pData->hErrRead) CloseHandle(pData->hErrRead);
5212 if (pData->hInWrite) CloseHandle(pData->hInWrite);
5219 AssignProcessToJobObject(ghJob, pData->procInfo.hProcess);
5226 pData->hJob = CreateJobObject(NULL, NULL);
5228 if (!AssignProcessToJobObject(pData->hJob, pData->procInfo.hProcess)) {
5229 CloseHandle(pData->hJob);
5234 return pData->procInfo.dwProcessId;
5244 (void)title; (void)ignoreOutput;
5249 int outPipe[2] = { -1, -1 }, errPipe[2] = { -1, -1 };
5250 if (captureOutput) {
5251 if (pipe(outPipe) != 0) {
5252 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessEx: could not create output pipes for '%s'", cmdline);
5255 if (pipe(errPipe) != 0) {
5256 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessEx: could not create output pipes for '%s'", cmdline);
5257 close(outPipe[0]); close(outPipe[1]);
5264 if (!posixUseShell) {
5267 if (captureOutput) { close(outPipe[0]); close(outPipe[1]); close(errPipe[0]); close(errPipe[1]); }
5281 req.
pid = -1; req.
done =
false;
5288 if (captureOutput) { close(outPipe[0]); close(outPipe[1]); close(errPipe[0]); close(errPipe[1]); }
5293 if (captureOutput) {
5296 fcntl(outPipe[0], F_SETFL, fcntl(outPipe[0], F_GETFL, 0) | O_NONBLOCK);
5297 fcntl(errPipe[0], F_SETFL, fcntl(errPipe[0], F_GETFL, 0) | O_NONBLOCK);
5299 pData->
outFD = outPipe[0];
5300 pData->
errFD = errPipe[0];
5310 if (!data || !len)
return false;
5315 if (!pData->hInWrite)
return false;
5317 while (written < len) {
5319 if (!WriteFile(pData->hInWrite, data + written, (DWORD)(len - written), &n, NULL) || !n) {
5324 written += (uint32)n;
5332 (void)proc; (void)data; (void)len;
5344 if (!pData->hInWrite)
return false;
5345 CloseHandle(pData->hInWrite);
5346 pData->hInWrite = NULL;
5360 HANDLE handles[2] = { pData->hOutRead, pData->hErrRead };
5361 std::string* targets[2] = { &out, &err };
5363 for (
int n = 0; n < 2; n++) {
5364 if (!handles[n])
continue;
5367 while (PeekNamedPipe(handles[n], NULL, 0, NULL, &avail, NULL) && avail) {
5368 DWORD toRead = avail <
sizeof(buf) ? avail : (DWORD)
sizeof(buf);
5370 if (!ReadFile(handles[n], buf, toRead, &got, NULL) || !got)
break;
5371 targets[n]->append(buf, got);
5384 std::string* targets[2] = { &out, &err };
5386 for (
int n = 0; n < 2; n++) {
5387 if (fds[n] < 0)
continue;
5389 while ((got = read(fds[n], buf,
sizeof(buf))) > 0)
5390 targets[n]->append(buf, (
size_t)got);
5401#if !defined(WINDOWS)
5413 const std::map<std::string, std::string>* env,
5414 uint16 cols, uint16 rows) {
5417 (void)cmdline; (void)initdir; (void)env; (void)cols; (void)rows;
5421 if (!cmdline || !*cmdline)
return 0;
5423 int master = posix_openpt(O_RDWR | O_NOCTTY);
5425 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessTerminal: posix_openpt failed (%d) for '%s'", errno, cmdline);
5428 if (grantpt(master) != 0 || unlockpt(master) != 0) {
5429 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessTerminal: grantpt/unlockpt failed (%d) for '%s'", errno, cmdline);
5433 char slaveName[256];
5434 #if defined(__APPLE__)
5435 const char* sn = ptsname(master);
5436 if (!sn) { close(master);
return 0; }
5437 strncpy(slaveName, sn,
sizeof(slaveName) - 1);
5438 slaveName[
sizeof(slaveName) - 1] = 0;
5440 if (ptsname_r(master, slaveName,
sizeof(slaveName)) != 0) { close(master);
return 0; }
5443 memset(&ws, 0,
sizeof(ws));
5444 ws.ws_col = cols ? cols : 80;
5445 ws.ws_row = rows ? rows : 25;
5446 ioctl(master, TIOCSWINSZ, &ws);
5449 if (pid < 0) { close(master);
return 0; }
5455 int slave = open(slaveName, O_RDWR);
5456 if (slave < 0) _exit(127);
5458 ioctl(slave, TIOCSCTTY, 0);
5460 dup2(slave, STDIN_FILENO);
5461 dup2(slave, STDOUT_FILENO);
5462 dup2(slave, STDERR_FILENO);
5463 if (slave > STDERR_FILENO) close(slave);
5464 if (initdir && *initdir && chdir(initdir) != 0) _exit(126);
5466 std::map<std::string, std::string>::const_iterator ei = env->begin();
5467 while (ei != env->end()) { setenv(ei->first.c_str(), ei->second.c_str(), 1); ei++; }
5469 execl(
"/bin/sh",
"sh",
"-c", cmdline, (
char*)NULL);
5473 fcntl(master, F_SETFL, fcntl(master, F_GETFL, 0) | O_NONBLOCK);
5476 (*TerminalMasterMap)[(uint32)pid] = master;
5484 (void)proc; (void)out;
5491 ssize_t got = read(fd, buf,
sizeof(buf));
5492 if (got > 0) { out.append(buf, (
size_t)got);
continue; }
5493 if (got == 0) { eofOut =
true;
break; }
5494 if (errno == EINTR)
continue;
5495 if (errno == EAGAIN || errno == EWOULDBLOCK)
break;
5508 (void)proc; (void)data; (void)len;
5511 if (!data || !len)
return false;
5515 while (written < len) {
5516 ssize_t n = write(fd, data + written, len - written);
5518 if (errno == EINTR)
continue;
5519 if (errno == EAGAIN || errno == EWOULDBLOCK) {
Sleep(2);
continue; }
5522 written += (uint32)n;
5530 (void)proc; (void)cols; (void)rows;
5536 memset(&ws, 0,
sizeof(ws));
5537 ws.ws_col = cols ? cols : 80;
5538 ws.ws_row = rows ? rows : 25;
5539 if (ioctl(fd, TIOCSWINSZ, &ws) != 0)
return false;
5540 kill(-(pid_t)proc, SIGWINCH);
5562 return (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, (DWORD)proc) != 0);
5564 return (kill((pid_t)proc, sig) == 0);
5574 if (WaitForSingleObject(pData->procInfo.hProcess, timeout) == WAIT_OBJECT_0) {
5575 if (GetExitCodeProcess(pData->procInfo.hProcess, &exitcode) && (exitcode == STILL_ACTIVE)) {
5580 CloseHandle(pData->procInfo.hProcess);
5581 CloseHandle(pData->procInfo.hThread);
5582 if (pData->hOutRead) CloseHandle(pData->hOutRead);
5583 if (pData->hErrRead) CloseHandle(pData->hErrRead);
5584 if (pData->hInWrite) CloseHandle(pData->hInWrite);
5585 if (pData->hJob) CloseHandle(pData->hJob);
5587 returncode = exitcode;
5594 HANDLE hproc = OpenProcess(NULL, NULL, (DWORD)proc);
5598 if (WaitForSingleObject(hproc, timeout) == WAIT_OBJECT_0) {
5599 if (GetExitCodeProcess(hproc, &exitcode) && (exitcode == STILL_ACTIVE)) {
5604 returncode = exitcode;
5648 for (n=1; n<argc; n++) {
5651 val = strchr(argv[n],
'=');
5690 if (p1 == std::string::npos) {
5691 if (p2 == std::string::npos)
5696 else if (p2 == std::string::npos)
5713 if (p1 == std::string::npos) {
5714 if (p2 == std::string::npos)
5719 else if (p2 == std::string::npos)
5746 std::map<std::string, std::string>::const_iterator it =
5762 FreeLibrary(handle);
5776 std::string realLibName;
5778 realLibName = filename;
5786 size_t slash = realLibName.find_last_of(
'/');
5787 int32 filenameStart = (slash == std::string::npos) ? 0 : (int32)(slash + 1);
5790 realLibName.insert(filenameStart,
"lib");
5792 if (!filenameStart) {
5794 realLibName.insert(0,
"./");
5796 realLibName.insert(0, path);
5806 std::string errorText;
5813 if (handle == NULL) {
5815 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
5816 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
5817 (LPTSTR)&lpMsgBuf, 0, NULL);
5818 LogPrint(0,
LOG_SYSTEM, 0,
"Could not find or load debug library '%sDebug': %s", filename, lpMsgBuf);
5819 LocalFree(lpMsgBuf);
5823 handle = LoadLibrary(filename);
5824 if (handle == NULL) {
5826 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
5827 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
5828 (LPTSTR) &lpMsgBuf, 0, NULL);
5829 LogPrint(0,
LOG_SYSTEM, 0,
"Could not find or load library '%s': %s", filename, lpMsgBuf);
5830 LocalFree(lpMsgBuf);
5836 const char* dlErrorText;
5843 std::string debugName = realLibName;
5846 handle = dlopen(debugName.c_str(), RTLD_NOW | RTLD_GLOBAL);
5848 dlErrorText = dlerror();
5850 if (dlErrorText && strlen(dlErrorText) &&
5851 !(strstr(dlErrorText,
"No such file") && strstr(dlErrorText, debugName.c_str())))
5852 errorText = dlErrorText;
5856 if (!handle && !errorText.size()) {
5861 if (strchr(filename,
'/'))
5862 handle = dlopen(realLibName.c_str(), RTLD_NOW | RTLD_GLOBAL);
5864 dlErrorText = dlerror();
5866 if (dlErrorText && strlen(dlErrorText) &&
5867 !(strstr(dlErrorText,
"No such file") && strstr(dlErrorText, realLibName.c_str())))
5868 errorText = dlErrorText;
5872 if (!handle && !errorText.size() && !strchr(filename,
'/')) {
5875 handle = dlopen(realLibName.c_str(), RTLD_NOW | RTLD_GLOBAL);
5877 dlErrorText = dlerror();
5879 if (dlErrorText && strlen(dlErrorText) &&
5880 !(strstr(dlErrorText,
"No such file") && strstr(dlErrorText, realLibName.c_str())))
5881 errorText = dlErrorText;
5885 if (handle == NULL) {
5886 if (errorText.size())
5887 LogPrint(0,
LOG_SYSTEM, 0,
"Could not load library file '%s': %s", realLibName.c_str(), errorText.c_str());
5899 if (!strlen(funcName))
5910 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
5911 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
5912 (LPTSTR) &lpMsgBuf, 0, NULL);
5913 LogPrint(0,
LOG_SYSTEM, 0,
"Could not find library function: %s: %s", funcName, lpMsgBuf);
5915 LocalFree(lpMsgBuf);
5923 if (errmsg != NULL) {
5924 LogPrint(0,
LOG_SYSTEM, 0,
"Could not find library function: %s: %s", (
char*) funcName, (
char*) errmsg);
5933 if (!lib->
load(libName)) {
5951 char* name =
new char[1024];
5982 std::string outString, errString;
5983 if (!
RunOSCommand(
"uname -n", NULL, 1000, outString, errString)) {
5999 HANDLE hProcess = GetCurrentProcess();
6000 PROCESS_MEMORY_COUNTERS pmc;
6001 if (hProcess == NULL)
6003 if ( GetProcessMemoryInfo( hProcess, &pmc,
sizeof(pmc)) != 0)
6004 return (uint64)pmc.WorkingSetSize;
6008 struct task_basic_info_64 info;
6009 mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
6010 if (task_info(mach_task_self(), TASK_BASIC_INFO_64, (task_info_t)&info, &count) == KERN_SUCCESS)
6011 return (uint64)info.resident_size;
6017 if ( (fp = fopen(
"/proc/self/statm",
"r" )) == NULL )
6019 if ( fscanf( fp,
"%*s%ld", &rss ) != 1 ) {
6024 return (uint64)rss * (uint64)sysconf( _SC_PAGESIZE);
6031 HANDLE hProcess = GetCurrentProcess();
6032 PROCESS_MEMORY_COUNTERS pmc;
6033 if (hProcess == NULL)
6035 if ( GetProcessMemoryInfo( hProcess, &pmc,
sizeof(pmc)) != 0)
6036 return (uint64)pmc.PeakWorkingSetSize;
6041 struct rusage usage;
6042 getrusage(RUSAGE_SELF, &usage);
6043 return (uint64)usage.ru_maxrss;
6046 struct rusage usage;
6047 getrusage( RUSAGE_SELF, &usage );
6048 return ((uint64)usage.ru_maxrss) * 1024L;
6070 SYSTEM_INFO siSysInfo;
6071 GetSystemInfo(&siSysInfo);
6072 return (uint16) siSysInfo.dwNumberOfProcessors;
6075 size_t len =
sizeof(ncpu);
6076 if (sysctlbyname(
"hw.ncpu", &ncpu, &len, NULL, 0) == 0 && ncpu > 0)
6077 return (uint16)(ncpu > 65535 ? 65535 : ncpu);
6080 long n = sysconf(_SC_NPROCESSORS_ONLN);
6082 return (uint16)(n > 65535 ? 65535 : (uint16)n);
6089 SYSTEM_INFO siSysInfo;
6090 GetSystemInfo(&siSysInfo);
6091 switch(siSysInfo.wProcessorArchitecture) {
6092 case PROCESSOR_ARCHITECTURE_AMD64:
6094 case PROCESSOR_ARCHITECTURE_IA64:
6096 case PROCESSOR_ARCHITECTURE_INTEL:
6102 #if defined(__x86_64__)
6104 #elif defined(__i386__)
6106 #elif defined(__aarch64__)
6112 #if defined(__x86_64__)
6114 #elif defined(__i386__)
6116 #elif defined(__aarch64__)
6148 size_t len =
sizeof(freq);
6149 if (sysctlbyname(
"hw.cpufrequency", &freq, &len, NULL, 0) == 0)
6154 std::ifstream cpuinfo(
"/proc/cpuinfo");
6156 while (cpuinfo && getline(cpuinfo, line)) {
6157 if (line.compare(0, 7,
"cpu MHz") == 0) {
6158 size_t colon = line.find(
':');
6159 if (colon != std::string::npos) {
6161 if (sscanf(line.c_str() + colon + 1,
"%lf", &mhz) == 1 && mhz > 0)
6162 return (uint64)(mhz * 1000000.0);
6173 MEMORYSTATUS memstat;
6174 GlobalMemoryStatus(&memstat);
6175 return (uint64)memstat.dwTotalPhys;
6179 size_t len =
sizeof(memsize);
6180 if (sysctlbyname(
"hw.memsize", &memsize, &len, NULL, 0) == 0)
6184 struct sysinfo info;
6185 if (sysinfo(&info) == 0)
6186 return info.totalram;
6196 MEMORYSTATUSEX memstat;
6197 memset(&memstat, 0,
sizeof(MEMORYSTATUSEX));
6198 memstat.dwLength =
sizeof(MEMORYSTATUSEX);
6199 if (!GlobalMemoryStatusEx(&memstat)) {
6200 int a = GetLastError();
6203 totalRAM = (uint64)memstat.ullTotalPhys;
6204 freeRAM = (uint64)memstat.ullAvailPhys;
6209 size_t len =
sizeof(memsize);
6210 if (sysctlbyname(
"hw.memsize", &memsize, &len, NULL, 0) != 0)
6213 vm_statistics64_data_t vm_stat;
6214 mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
6215 if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t)&vm_stat, &count) != KERN_SUCCESS)
6217 vm_size_t page_size;
6218 if (host_page_size(mach_host_self(), &page_size) != KERN_SUCCESS)
6220 freeRAM = (uint64)vm_stat.free_count * (uint64)page_size;
6223 struct sysinfo info;
6224 if (sysinfo(&info) == 0) {
6225 totalRAM = info.totalram;
6226 freeRAM = info.freeram;
6238 SYSTEM_INFO siSysInfo;
6239 GetSystemInfo(&siSysInfo);
6241 switch(siSysInfo.wProcessorArchitecture) {
6242 case PROCESSOR_ARCHITECTURE_UNKNOWN:
6244 case PROCESSOR_ARCHITECTURE_INTEL:
6245 switch(siSysInfo.wProcessorLevel) {
6271 case PROCESSOR_ARCHITECTURE_MIPS:
6274 case PROCESSOR_ARCHITECTURE_ALPHA:
6277 case PROCESSOR_ARCHITECTURE_PPC:
6280 case PROCESSOR_ARCHITECTURE_IA64:
6283 case PROCESSOR_ARCHITECTURE_AMD64:
6297 if (strlen(
OSName) == 0) {
6333 BOOL bOsVersionInfoEx;
6338 ZeroMemory(&osvi,
sizeof(OSVERSIONINFO));
6339 osvi.dwOSVersionInfoSize =
sizeof(OSVERSIONINFO);
6341 if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
6343 osvi.dwOSVersionInfoSize =
sizeof (OSVERSIONINFO);
6344 if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
6348 major = osvi.dwMajorVersion;
6349 minor = osvi.dwMinorVersion;
6350 if (strlen((
char*)osvi.szCSDVersion) < textSize)
6354 OSVERSIONINFOEX osvi;
6355 BOOL bOsVersionInfoEx;
6360 ZeroMemory(&osvi,
sizeof(OSVERSIONINFOEX));
6361 osvi.dwOSVersionInfoSize =
sizeof(OSVERSIONINFOEX);
6363 if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
6365 osvi.dwOSVersionInfoSize =
sizeof (OSVERSIONINFO);
6366 if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
6370 switch (osvi.dwPlatformId)
6373 case VER_PLATFORM_WIN32_NT:
6377 if( osvi.dwMajorVersion == 4 &&
6378 lstrcmpi( osvi.szCSDVersion,
"Service Pack 6" ) == 0 )
6384 lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
6385 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
6386 0, KEY_QUERY_VALUE, &hKey );
6387 if( lRet == ERROR_SUCCESS ) {
6390 build = osvi.dwBuildNumber & 0xFFFF;
6394 major = (uint16)osvi.dwMajorVersion;
6395 minor = (uint16)osvi.dwMinorVersion;
6396 build = (uint16)osvi.dwBuildNumber & 0xFFFF;
6397 if (strlen((
char*)osvi.szCSDVersion) < textSize)
6400 RegCloseKey( hKey );
6404 major = (uint16)osvi.dwMajorVersion;
6405 minor = (uint16)osvi.dwMinorVersion;
6406 build = (uint16)osvi.dwBuildNumber & 0xFFFF;
6408 if (strlen((
char*)osvi.szCSDVersion) < textSize)
6475char*
Int2Ascii(int64 value,
char* result, uint16 size, uint8 base) {
6476 if (base < 2 || base > 36) {
6481 char* ptr = result, *ptr1 = result, tmp_char;
6487 *ptr++ =
"zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
6502char*
Uint2Ascii(uint64 value,
char* result, uint16 size, uint8 base) {
6503 if (base < 2 || base > 36) {
6508 char* ptr = result, *ptr1 = result, tmp_char;
6514 *ptr++ =
"zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
6527 size = (len * 2) + 4;
6528 unsigned char* result =
new unsigned char[size];
6532 const char* src = ascii;
6533 for (uint32 n = 0; n < len; n++) {
6540 size = (len * 2) + 2;
6545bool GetSocketError(
int error,
char* errorString, uint16 errorStringMaxSize,
bool* isRecoverable) {
6547 if (errorStringMaxSize < 128)
6552 if (error == WSANOTINITIALISED) {
6553 utils::strcpyavail(errorString,
"Cannot initialize WinSock!", errorStringMaxSize,
true);
6554 *isRecoverable =
false;
6556 else if (error == WSAENETDOWN) {
6557 utils::strcpyavail(errorString,
"The network subsystem or the associated service provider has failed", errorStringMaxSize,
true);
6558 *isRecoverable =
false;
6560 else if (error == WSAEAFNOSUPPORT) {
6561 utils::strcpyavail(errorString,
"The specified address family is not supported", errorStringMaxSize,
true);
6562 *isRecoverable =
false;
6564 else if (error == WSAEINPROGRESS) {
6565 utils::strcpyavail(errorString,
"A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function", errorStringMaxSize,
true);
6566 *isRecoverable =
true;
6568 else if (error == WSAEMFILE) {
6569 utils::strcpyavail(errorString,
"No more socket descriptors are available", errorStringMaxSize,
true);
6570 *isRecoverable =
false;
6572 else if (error == WSAENOBUFS) {
6573 utils::strcpyavail(errorString,
"No buffer space is available. The socket cannot be created", errorStringMaxSize,
true);
6574 *isRecoverable =
false;
6576 else if (error == WSAEPROTONOSUPPORT) {
6577 utils::strcpyavail(errorString,
"The specified protocol is not supported", errorStringMaxSize,
true);
6578 *isRecoverable =
false;
6580 else if (error == WSAEPROTOTYPE) {
6581 utils::strcpyavail(errorString,
"The specified protocol is the wrong type for this socket", errorStringMaxSize,
true);
6582 *isRecoverable =
false;
6584 else if (error == WSAESOCKTNOSUPPORT) {
6585 utils::strcpyavail(errorString,
"The specified socket type is not supported in this address family", errorStringMaxSize,
true);
6586 *isRecoverable =
false;
6588 else if (error == WSAEADDRINUSE) {
6589 utils::strcpyavail(errorString,
"The socket's local address is already in use and the socket was not marked to allow address reuse with SO_REUSEADDR. This error usually occurs during execution of the bind function, but could be delayed until this function if the bind was to a partially wildcard address (involving ADDR_ANY) and if a specific address needs to be committed at the time of this function", errorStringMaxSize,
true);
6590 *isRecoverable =
false;
6592 else if (error == WSAEINVAL) {
6593 utils::strcpyavail(errorString,
"The socket has not been bound with bind", errorStringMaxSize,
true);
6594 *isRecoverable =
false;
6596 else if (error == WSAEISCONN) {
6597 utils::strcpyavail(errorString,
"The socket is already connected", errorStringMaxSize,
true);
6598 *isRecoverable =
false;
6600 else if (error == WSAENOTSOCK) {
6601 utils::strcpyavail(errorString,
"The descriptor is not a socket", errorStringMaxSize,
true);
6602 *isRecoverable =
false;
6604 else if (error == WSAEOPNOTSUPP) {
6605 utils::strcpyavail(errorString,
"The referenced socket is not of a type that supports the listen operation", errorStringMaxSize,
true);
6606 *isRecoverable =
false;
6608 else if (error == WSAEADDRNOTAVAIL) {
6609 utils::strcpyavail(errorString,
"The specified address is not a valid address for this machine", errorStringMaxSize,
true);
6610 *isRecoverable =
false;
6612 else if (error == WSAEFAULT) {
6613 utils::strcpyavail(errorString,
"The name or namelen parameter is not a valid part of the user address space", errorStringMaxSize,
true);
6614 *isRecoverable =
false;
6616 else if (error == WSAEMFILE) {
6617 utils::strcpyavail(errorString,
"The queue is nonempty upon entry to accept and there are no descriptors available", errorStringMaxSize,
true);
6618 *isRecoverable =
false;
6621 utils::strcpyavail(errorString,
"The socket is marked as nonblocking and no connections are present to be accepted", errorStringMaxSize,
true);
6622 *isRecoverable =
false;
6624 else if (error == WSAETIMEDOUT) {
6625 utils::strcpyavail(errorString,
"Attempt to connect timed out without establishing a connection", errorStringMaxSize,
true);
6626 *isRecoverable =
false;
6628 else if (error == WSAENETUNREACH) {
6629 utils::strcpyavail(errorString,
"The network cannot be reached from this host at this time", errorStringMaxSize,
true);
6630 *isRecoverable =
false;
6632 else if (error == WSAEISCONN) {
6633 utils::strcpyavail(errorString,
"The socket is already connected (connection-oriented sockets only)", errorStringMaxSize,
true);
6634 *isRecoverable =
false;
6636 else if (error == WSAECONNREFUSED) {
6637 utils::strcpyavail(errorString,
"The attempt to connect was forcefully rejected", errorStringMaxSize,
true);
6638 *isRecoverable =
false;
6640 else if (error == WSAEAFNOSUPPORT) {
6641 utils::strcpyavail(errorString,
"Addresses in the specified family cannot be used with this socket", errorStringMaxSize,
true);
6642 *isRecoverable =
false;
6644 else if (error == WSAEADDRNOTAVAIL) {
6645 utils::strcpyavail(errorString,
"The remote address is not a valid address (such as ADDR_ANY)", errorStringMaxSize,
true);
6646 *isRecoverable =
false;
6648 else if (error == WSAEALREADY) {
6649 utils::strcpyavail(errorString,
"A nonblocking connect call is in progress on the specified socket", errorStringMaxSize,
true);
6650 *isRecoverable =
false;
6652 else if (error == WSAECONNRESET) {
6654 *isRecoverable =
false;
6656 else if (error == WSAECONNABORTED) {
6657 utils::strcpyavail(errorString,
"Software caused connection abort", errorStringMaxSize,
true);
6658 *isRecoverable =
false;
6661 snprintf(errorString, errorStringMaxSize,
"TCP error with no description: %d", error);
6662 *isRecoverable =
false;
6668 utils::strcpyavail(errorString,
"Cannot initialise socket", errorStringMaxSize,
true);
6669 *isRecoverable =
false;
6673 *isRecoverable =
false;
6683 int err = WSAGetLastError();
6694 DWORD error = GetLastError();
6695 uint32 len = FormatMessage(
6696 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
6697 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
6698 (LPTSTR) &lpMsgBuf, 0, NULL);
6699 std::string str = (
char*)lpMsgBuf;
6700 LocalFree(lpMsgBuf);
6730 ldiv_t d = ldiv(timeout*1000, 1000000);
6736 return( select(maxfd, NULL, &wds, NULL, &tv) > 0);
6762 ldiv_t d = ldiv(timeout*1000, 1000000);
6769 int ret = select(maxfd, &rdds, NULL, NULL, &tv);
6777 #if defined(WINDOWS)
6778 unsigned long parm = 1;
6779 ioctlsocket(s, FIONBIO, &parm);
6781 long parm = fcntl(s, F_GETFL);
6783 fcntl(s, F_SETFL, parm);
6789 #if defined(WINDOWS)
6790 unsigned long parm = 0;
6791 ioctlsocket(s, FIONBIO, &parm);
6793 long parm = fcntl(s, F_GETFL);
6794 parm &= ~O_NONBLOCK;
6795 fcntl(s, F_SETFL, parm);
6802 if ( (name == NULL) || (strlen(name) == 0) )
6818 struct addrinfo hints, *res;
6820 const char *cause = NULL;
6822 memset(&hints, 0,
sizeof(hints));
6825 hints.ai_family = AF_INET;
6826 hints.ai_socktype = SOCK_STREAM;
6827 hints.ai_protocol = IPPROTO_TCP;
6829 error = getaddrinfo(name, NULL, &hints, &res);
6831 __except (EXCEPTION_CONTINUE_EXECUTION) {
6836 memcpy(&address, res->ai_addr->sa_data + 2,
sizeof(address));
6846 struct addrinfo hints, *res;
6848 const char *cause = NULL;
6850 memset(&hints, 0,
sizeof(hints));
6852 hints.ai_family = PF_UNSPEC;
6853 hints.ai_socktype = SOCK_STREAM;
6854 error = getaddrinfo(name, NULL, &hints, &res);
6856 memcpy(&address, res->ai_addr->sa_data+2, 4);
6866 bool IsNetworkInitialised =
false;
6867 bool CheckNetworkInit() {
6868 if (IsNetworkInitialised)
return true;
6870 if (WSAStartup(MAKEWORD(1,1), &info) != 0) {
6874 IsNetworkInitialised =
true;
6881 struct hostent *pHost;
6883 unsigned char* addrChars = (
unsigned char*)&address;
6885 char* addrString =
new char[20];
6886 snprintf(addrString, 20,
"%u.%u.%u.%u", addrChars[0], addrChars[1], addrChars[2], addrChars[3]);
6889 pHost = gethostbyname(addrString);
6890 delete [] addrString;
6891 if (pHost == NULL) {
6894 if (strlen(pHost->h_name) > maxSize-1) {
6902 pHost = gethostbyname(addrString);
6903 delete [] addrString;
6907 if (strlen(pHost->h_name) > maxSize-1)
6914 pHost =
new struct hostent;
6917 gethostbyname_r(addrString, pHost, bf, 2000, &pHost, &er);
6918 delete [] addrString;
6924 if (strlen(pHost->h_name) > maxSize-1)
6936 char* name =
new char[256];
6942 std::string sname = name;
6950 if (gethostname(name, maxSize) == 0)
7011 for (uint32 i=0; i<c; i++) {
7012 if ( (interfaces[i].address != 0) && (interfaces[i].address !=
LOCALHOSTIP) )
7013 address = interfaces[i].
mac;
7015 delete [] interfaces;
7016 return (address != 0);
7024 uint64* addresses =
new uint64[c];
7026 for (uint32 i=0; i<c; i++) {
7027 if ( (interfaces[i].address != 0) && (interfaces[i].address !=
LOCALHOSTIP) )
7028 addresses[p++] = interfaces[i].
mac;
7045 if ((addresses == NULL) || (count == 0)) {
7046 delete [] addresses;
7051 for (n=0; n<count; n++) {
7052 if (addresses[n] == address) {
7053 delete [] addresses;
7057 delete [] addresses;
7065 if ((addresses == NULL) || (count == 0)) {
7066 delete [] addresses;
7071 bool localhostPresent =
false;
7072 for (n=0; n<count; n++) {
7074 if (addresses[n] != 0) {
7075 address = addresses[n];
7076 delete [] addresses;
7081 localhostPresent =
true;
7083 delete [] addresses;
7085 if (localhostPresent) {
7096 uint32 maxSize = 128;
7097 uint32* addresses =
new uint32[maxSize];
7102 char* szHostName =
new char[255];
7104 bool canAskHost =
true;
7105 if( gethostname(szHostName, 255) != 0 ) {
7108 if (err == WSANOTINITIALISED) {
7110 if (WSAStartup(MAKEWORD(1,1), &info) != 0) {
7111 delete [] szHostName;
7115 if( gethostname(szHostName, 255) != 0 )
7126 struct hostent * pHost;
7129 #if !defined(WINDOWS) && !defined(Darwin)
7135 char* hostBuf = NULL;
7136 struct hostent* hostAlloc = NULL;
7143 pHost = gethostbyname(szHostName);
7147 pHost = gethostbyname(szHostName);
7152 hostAlloc =
new struct hostent;
7153 hostBuf =
new char[2000];
7155 struct hostent* hres = NULL;
7156 int res = gethostbyname_r(szHostName, hostAlloc, hostBuf, 2000, &hres, &er);
7163 if ((res != 0) || (hres == NULL))
7170 for( i = 0; pHost!= NULL && pHost->h_addr_list[i]!= NULL; i++ )
7173 memcpy(&addr, ((
unsigned char*)pHost->h_addr_list[i]),
sizeof(uint32));
7175 for (j=0; j<count; j++) {
7176 if (addresses[j] == addr) {
7182 addresses[count++] = addr;
7200 for (i=0; i<c; i++) {
7202 if ( (interfaces[i].address != 0) && (interfaces[i].address !=
LOCALHOSTIP) ) {
7203 for (j=0; j<count; j++) {
7204 if (addresses[j] == interfaces[i].address) {
7210 addresses[count++] = interfaces[i].
address;
7213 delete [] interfaces;
7214 delete [] szHostName;
7221 uint32 maxSize = 128;
7234 ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
7237 ULONG family = AF_INET;
7239 LPVOID lpMsgBuf = NULL;
7241 PIP_ADAPTER_ADDRESSES pAddresses = NULL;
7242 ULONG outBufLen = 0;
7243 ULONG Iterations = 0;
7245 PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
7246 PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
7247 PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
7248 PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
7249 IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
7250 IP_ADAPTER_PREFIX *pPrefix = NULL;
7257 pAddresses = (IP_ADAPTER_ADDRESSES *)
MALLOC(outBufLen);
7258 if (pAddresses == NULL)
7262 GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
7264 if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
7273 }
while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < 10));
7276 if (dwRetVal == NO_ERROR) {
7278 pCurrAddresses = pAddresses;
7279 while (pCurrAddresses) {
7280 if ( (pCurrAddresses->OperStatus == IfOperStatusUp) && (pCurrAddresses->IfIndex != 0)) {
7283 pUnicast = pCurrAddresses->FirstUnicastAddress;
7284 if (pUnicast != NULL) {
7285 for (i = 0; pUnicast != NULL; i++) {
7286 addr = *(uint32*)(((
unsigned char*) ((
SOCKADDR*)(pUnicast->Address.lpSockaddr))->sa_data) + 2);
7288 interfaces[count].
address = addr;
7289 interfaces[count].
mac = 0;
7290 if (pCurrAddresses->PhysicalAddressLength == 6)
7291 memcpy(&(interfaces[count].mac), &(pCurrAddresses->PhysicalAddress), 6);
7292 WideCharToMultiByte( CP_ACP, 0, pCurrAddresses->Description, -1, interfaces[count].
name,
MAXKEYNAMELEN, NULL, NULL );
7293 WideCharToMultiByte( CP_ACP, 0, pCurrAddresses->FriendlyName, -1, interfaces[count].
friendlyName,
MAXKEYNAMELEN, NULL, NULL );
7296 pUnicast = pUnicast->Next;
7301 pCurrAddresses = pCurrAddresses->Next;
7312 struct sockaddr_in *saptr = NULL;
7313 struct if_nameindex *iflist = NULL, *listsave = NULL;
7316 if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
7321 iflist = listsave = if_nameindex();
7323 if (iflist == NULL) {
7331 for(; iflist->if_index != 0; iflist++) {
7333 strncpy(ifreq.ifr_name, iflist->if_name, IF_NAMESIZE);
7335 if(ioctl(sock, SIOCGIFADDR, &ifreq) != 0) {
7340 saptr = (
struct sockaddr_in *)&ifreq.ifr_addr;
7343 memcpy(&(interfaces[count].address), &(saptr->sin_addr.s_addr),
sizeof(uint32));
7346 interfaces[count].
mac = 0;
7349 interfaces[count].
mac = 0;
7350 ioctl(sock, SIOCGIFHWADDR, &ifreq);
7351 memcpy(&(interfaces[count].mac), &(ifreq.ifr_hwaddr.sa_data), 6);
7356 if_freenameindex(listsave);
7368 struct sockaddr_in addr;
7369 addr.sin_family= AF_INET;
7370 addr.sin_addr.s_addr=INADDR_ANY;
7371 bool result =
false;
7373 nextPort = lastPort + 1;
7374 while (nextPort < lastPort + 1000) {
7375 if((socket=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==
INVALID_SOCKET)
7382 setsockopt(socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (
char *) &one,
sizeof(one));
7394 setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&one,
sizeof(one));
7397 addr.sin_port=htons(nextPort);
7413 printf(
"Testing Utils...\n\n");
7415 char hostname[1024];
7417 printf(
"Error GetLocalHostname\n");
7420 printf(
"Local Hostname: '%s'\n\n", hostname);
7423 unsigned char* addrChars = (
unsigned char*) &addr;
7425 printf(
"Error GetLocalIPAddress\n");
7428 printf(
"Local IP Address: %u.%u.%u.%u\n\n", addrChars[0], addrChars[1], addrChars[2], addrChars[3]);
7432 if (addresses == NULL) {
7433 printf(
"Error GetLocalIPAddresses\n");
7437 for (n=0; n<count; n++) {
7438 addrChars = (
unsigned char*) &addresses[n];
7439 printf(
"Local IP Address[%u]: %u.%u.%u.%u (%u,%u)\n\n", n, addrChars[0], addrChars[1], addrChars[2], addrChars[3], addresses[n],
LOCALHOSTIP);
7441 delete [] addresses;
7444 for (n=0; n<count; n++) {
7445 addrChars = (
unsigned char*) &(interfaces[n]);
7446 printf(
"Local Interface[%u] %s: %u.%u.%u.%u (%llX)\n\n", n, interfaces[n].name,
7447 addrChars[0], addrChars[1], addrChars[2], addrChars[3], interfaces[n].mac);
7449 delete [] interfaces;
7454void PrintBinary(
void* p, uint32 size,
bool asInt,
const char* title) {
7456 printf(
"--- %s %u ---\n", title, size);
7458 for (uint32 n=0; n<size; n++) {
7459 c = *(((
unsigned char*)p)+n);
7461 printf(
"[%u] ", (
unsigned int)c);
7464 if ( (n > 0) && ((n+1)%10 == 0) )
7489const char*
stristr(
const char *str,
const char *substr, uint32 len) {
7490 if (!str || !substr)
return NULL;
7491 uint32 sslen = (uint32)strlen(substr);
7492 if (sslen == 0)
return (
const char*)str;
7495 for (; *str; str++, n++) {
7500 while ((*a++ | 32) == (*b++ | 32)) {
7503 if (len && (++m > len))
7510uint32
strcpyavail(
char* dst,
const char* src, uint32 maxlen,
bool copyAvailable) {
7511 if ( !dst || ! src || !maxlen )
7513 uint32 len = (uint32)strlen(src);
7514 if (len > maxlen-1) {
7518 memcpy(dst, src, maxlen-1);
7524 memcpy(dst, src, len+1);
7532 for (len = 0; len < size; len++) {
7534 if (str[len] == 13) {
7535 crSize = ( (len < size-1) && (str[len+1] == 10 ) ) ? 2 : 1;
7539 if (str[len] == 10) {
7550 std::string str = text;
7553 std::string::iterator i = str.begin(), e = str.end();
7557 std::transform(i, e, i, ::tolower);
7562 std::string str = text;
7563 std::transform(str.begin(), str.end(), str.begin(), ::toupper);
7568 std::string str = text;
7569 std::transform(str.begin(), str.end(), str.begin(), ::tolower);
7575 std::vector<std::string>::iterator i = lines.begin(), e = lines.end();
7585 uint32 len = (uint32)strlen(text);
7586 if (!len)
return "";
7591 uint32 s = 0, p = 0;
7593 while ( ((text[s] ==
'\n') || (text[s] ==
'\r')) && (s < len))
7596 while ((text[p] <= 32) && (p < len))
7598 std::string indentString = std::string(text+s, p-s);
7599 std::string str = text;
7607 uint32 begin = 0, end = (uint32)strlen(text);
7610 while ((begin < end) && (text[begin] <= 32) || (text[begin] ==
'\"') || (text[begin] ==
'\''))
7614 while ((end > begin) && (text[end-1] <= 32) || (text[end-1] ==
'\"') || (text[end-1] ==
'\''))
7616 return std::string(text+begin, end-begin);
7625 uint32 begin = 0, end = (uint32)strlen(text);
7628 while ((text[begin] <= 32) && (begin < end))
7630 while ((end > begin) && (text[end-1] <= 32))
7632 return std::string(text+begin, end-begin);
7638std::multimap<std::string, std::string>
TextMultiMapSplit(
const char* text,
const char* outersplit,
const char* innersplit) {
7639 std::multimap<std::string, std::string> result;
7640 typedef std::pair <std::string, std::string> Map_String_Pair;
7642 if (!text || !outersplit || !innersplit)
7645 const char* pstr = text, *lstr = text;
7646 const char* src = text;
7648 while (pstr = strstr(src, outersplit)) {
7649 if ((lstr = strstr(src, innersplit)) && (lstr < pstr)) {
7651 result.insert(Map_String_Pair(
TextTrim(std::string(src, lstr-src).c_str()),
TextTrim(std::string(lstr+1, pstr-lstr-1).c_str())));
7655 pstr = src + strlen(src);
7656 if ((lstr = strstr(src, innersplit)) && (lstr < pstr)) {
7658 result.insert(Map_String_Pair(
TextTrim(std::string(src, lstr-src).c_str()),
TextTrim(std::string(lstr+1, pstr-lstr-1).c_str())));
7665std::map<std::string, std::string>
TextMapSplit(
const char* text,
const char* outersplit,
const char* innersplit) {
7666 std::map<std::string, std::string> result;
7667 typedef std::pair <std::string, std::string> Map_String_Pair;
7669 if (!text || !outersplit || !innersplit)
7672 const char* pstr = text, *lstr = text;
7673 const char* src = text;
7675 while (pstr = strstr(src, outersplit)) {
7676 if ((lstr = strstr(src, innersplit)) && (lstr < pstr)) {
7678 result.insert(Map_String_Pair(
TextTrim(std::string(src, lstr - src).c_str()),
TextTrim(std::string(lstr + 1, pstr - lstr - 1).c_str())));
7682 pstr = src + strlen(src);
7683 if ((lstr = strstr(src, innersplit)) && (lstr < pstr)) {
7685 result.insert(Map_String_Pair(
TextTrim(std::string(src, lstr - src).c_str()),
TextTrim(std::string(lstr + 1, pstr - lstr - 1).c_str())));
7693 uint32 size = (uint32)args.size();
7697 char** argv =
new char*[size+1];
7699 std::vector<std::string>::iterator i = args.begin(), e = args.end();
7701 argv[c] =
new char[(*i).length()+1];
7702 strcpy(argv[c], (*i).c_str());
7713 uint32 size = (uint32)args.size();
7717 wchar_t** argv =
new wchar_t*[size+1];
7719 std::vector<std::string>::iterator i = args.begin(), e = args.end();
7721 argv[c] =
new wchar_t[(*i).length()+1];
7722 mbstowcs(argv[c], (*i).c_str(), (*i).length() + 1);
7732 for (uint32 n=0; n<(uint32)argc; n++)
7740 bool insideQuotes =
false;
7741 bool lastWasWhiteSpace =
false;
7742 std::vector<std::string> vect;
7743 std::string arg, val, str;
7746 uint32 len = (uint32)strlen(cmdline);
7748 bool keepQuotes =
false;
7750 for (uint32 n=0; n<len; n++) {
7753 if (!insideQuotes) {
7754 if (!lastWasWhiteSpace) {
7756 vect.push_back(str);
7762 lastWasWhiteSpace =
true;
7768 else if (ch ==
'"') {
7769 insideQuotes = !insideQuotes;
7772 lastWasWhiteSpace =
false;
7776 lastWasWhiteSpace =
false;
7780 if (str.length() > 0) {
7781 vect.push_back(str);
7789 if (!text || !strlen(text))
7790 return std::vector<std::string>();
7792 if (strstr(text,
"\r\n"))
7794 else if (strstr(text,
"\n\r"))
7796 else if (strstr(text,
"\n"))
7798 else if (strstr(text,
"\r"))
7801 std::vector<std::string> result;
7802 result.push_back(text);
7807 if (!text || !strlen(text))
7808 return std::vector<std::string>();
7811 std::vector<std::string> result;
7812 uint32 s = 0, n = 0, len = (uint32)strlen(text);
7815 if (text[n] == 13) {
7817 result.push_back(
"");
7819 str = std::string(text + s, n - s);
7820 result.push_back(
TextTrim(str.c_str()));
7822 if ((n < len - 1) && (text[n + 1] == 10))
7828 else if (text[n] == 10) {
7830 result.push_back(
"");
7832 str = std::string(text + s, n - s);
7833 result.push_back(
TextTrim(str.c_str()));
7835 if ((n < len - 1) && (text[n + 1] == 13))
7841 else if ((n-s < maxLineLength) && (text[n] == 32)) {
7844 else if (n - s >= maxLineLength) {
7846 result.push_back(
"");
7852 str = std::string(text + s, p);
7853 result.push_back(
TextTrim(str.c_str()));
7859 str = std::string(text + s, maxLineLength);
7860 result.push_back(
TextTrim(str.c_str()));
7869 str = std::string(text + s, n - s);
7870 result.push_back(
TextTrim(str.c_str()));
7884std::string
TextJoin(std::vector<std::string> &list,
const char* split, uint32 start, uint32 count) {
7885 std::ostringstream o;
7886 std::vector<std::string>::iterator i = list.begin(), e = list.end();
7887 uint32 l = 0, c = 0;
7889 if (!count || ((l >= start) && (c < count))) {
7890 if (c++) o << split;
7899std::string
TextJoin(std::list<std::string> &list,
const char* split, uint32 start, uint32 count) {
7900 std::ostringstream o;
7901 std::list<std::string>::iterator i = list.begin(), e = list.end();
7902 uint32 l = 0, c = 0;
7904 if (!count || ((l >= start) && (c < count))) {
7905 if (c++) o << split;
7914std::string
TextJoin(std::map<std::string, std::string> &map,
const char* innersplit,
const char* outersplit,
bool keyquotes,
bool valquotes) {
7915 std::ostringstream o;
7916 std::map<std::string, std::string>::iterator i = map.begin(), e = map.end();
7919 if (c++) o << outersplit;
7920 if (keyquotes && valquotes)
7921 o <<
"\"" << i->first <<
"\"" << innersplit <<
"\"" << i->second <<
"\"";
7923 o << i->first << innersplit <<
"\"" << i->second <<
"\"";
7925 o << i->first << innersplit << i->second;
7932 std::ostringstream o;
7933 std::map<std::string, std::string>::iterator i = map.begin(), e = map.end();
7947std::string
TextJoinXML(std::map<std::string, std::string> &map,
const char* innernodeName,
const char* outernodeName) {
7948 if (!innernodeName || !strlen(innernodeName))
7950 std::ostringstream o;
7951 std::map<std::string, std::string>::iterator i = map.begin(), e = map.end();
7952 if (outernodeName && strlen(outernodeName))
7953 o <<
"<" << outernodeName <<
">\n";
7958 if (outernodeName && strlen(outernodeName))
7959 o <<
"</" << outernodeName <<
">\n";
7965std::vector<std::string>
TextListSplit(
const char* text,
const char* split,
bool keepEmpty,
bool autoTrim) {
7966 std::vector<std::string> result;
7967 if (!text || !split)
7970 uint32 splitLen = (uint32)strlen(split);
7971 const char* pstr = text;
7972 const char* src = text;
7974 while (pstr = strstr(src, split)) {
7975 if (pstr - src || keepEmpty) {
7977 result.push_back(
TextTrim(std::string(src, pstr - src).c_str()));
7979 result.push_back(std::string(src, pstr - src).c_str());
7981 src = pstr + splitLen;
7983 pstr = src + strlen(src);
7986 result.push_back(
TextTrim(std::string(src, pstr - src).c_str()));
7988 result.push_back(std::string(src, pstr - src).c_str());
7995 std::vector<std::string>::iterator i, e;
7996 for (i=vect.begin(), e=vect.end(); i!=e; i++) {
7997 if (allowEmpty || (*i).size()) {
8007 if (strlen(format) == 0) {
8013 va_start(args, format);
8024 int len = _vscprintf(format, orig_args) + 10;
8025 str = (
char*)malloc(len+1);
8027 len = vsnprintf(str, len, format, orig_args);
8029 len = _vsnprintf_s(str, len, len+1, format, orig_args);
8033 size = (uint32)strlen(str);
8040 int len = vasprintf(&str, format, orig_args);
8051 if (!dst || !maxsize)
8053 if (strlen(format) == 0) {
8060 va_start(args, format);
8064 if (len > maxsize) {
8081 if (strlen(format) == 0)
8087 va_start(args, format);
8099 if (!text.size() || !key.size())
8104 uint32 keylen = (uint32)key.size();
8106 while ( (p = text.find(key, p)) != std::string::npos) {
8107 text.replace(p, keylen, value);
8117 if (!text.size() || !map.size())
8122 std::map<std::string, std::string>::iterator it, itEnd;
8123 for (it = map.begin(), itEnd = map.end(); it != itEnd; ++it)
8150uint32
StringScriptReplace(std::string& text, std::string name, std::list<std::map<std::string, std::string> >& list) {
8151 if (!text.size() || !name.size())
8156 char* start =
new char[name.size() + 50];
8157 snprintf(start, name.size()+50,
"<!-- start:%s -->", name.c_str());
8158 char* end =
new char[name.size() + 50];
8159 snprintf(end, name.size()+50,
"<!-- end:%s -->", name.c_str());
8162 size_t a1 = text.find(start);
8163 if (a1 == std::string::npos) {
8168 size_t b1 = text.find(end);
8169 if (b1 == std::string::npos) {
8175 uint32 a2 = (uint32)(a1 + strlen(start));
8176 uint32 b2 = (uint32)(b1 + strlen(end));
8179 std::string section = text.substr(a2, b1-a2);
8183 std::list<std::map<std::string, std::string> >::iterator it, itEnd;
8184 for (it = list.begin(), itEnd = list.end(); it != itEnd; ++it) {
8190 text.replace(a1, b2-a1, result);
8199 unsigned char c = (
unsigned char) strtol(str, NULL, 16);
8207 unsigned char c = (
unsigned char) strtol(str, NULL, 10);
8215 float64 diff = a - b;
8216 if ((diff < std::numeric_limits<float64>::epsilon()) && (-diff < std::numeric_limits<float64>::epsilon()))
8225#define poly 0xEDB88320
8233int CRC32(
const char *addr, uint32 length, int32 crc) {
8235 for (; length>0; length--) {
8236 crc = crc ^ *addr++;
8237 for (i=0; i<8; i++) {
8239 crc = (crc >> 1) ^
poly;
8253 char* data =
ReadAFile(filename.c_str(), length,
false);
8254 if (!data || !length)
8256 std::string dataString = data;
8261char*
ReadAFile(
const char* dir,
const char* filename, uint32& length,
bool binary) {
8262 if (!dir || !filename || strlen(filename) == 0)
8265 char* fullname =
new char[strlen(dir) + strlen(filename) + 5];
8266 snprintf(fullname, strlen(dir) + strlen(filename) + 5,
"%s/%s", dir, filename);
8267 char* res =
ReadAFile(fullname, length, binary);
8272char*
ReadAFile(
const char* filename, uint32& length,
bool binary) {
8273 if (!filename || strlen(filename) == 0)
8280 file = fopen(filename,
"rb");
8282 file = fopen(filename,
"r");
8288 fseek(file, 0, SEEK_END);
8289 length = ftell(file);
8290 fseek(file, 0, SEEK_SET);
8298 char* data =
new char[length+1];
8300 int res = (int)fread(data, 1, length, file);
8302 if ((res <= 0) || (res != length)) {
8303 int error = ferror(file);
8304 int eof = feof(file);
8308 LogPrint(0,0,0,
"File %s has no data", filename);
8315 length = (uint32)res;
8320bool WriteAFile(
const char* dir,
const char* filename,
const char* data, uint32 length,
bool binary) {
8321 if (!dir || !filename || strlen(filename) == 0)
8324 char* fullname =
new char[strlen(dir) + strlen(filename) + 5];
8325 snprintf(fullname, strlen(dir) + strlen(filename) + 5,
"%s/%s", dir, filename);
8326 bool res =
WriteAFile(fullname, data, length, binary);
8331bool WriteAFile(
const char* filename,
const char* data, uint32 length,
bool binary) {
8332 if (!filename || strlen(filename) == 0)
8337 file = fopen(filename,
"wb");
8339 file = fopen(filename,
"w");
8343 int res = (int)fwrite(data, 1, length, file);
8345 return (res == length);
8348bool AppendToAFile(
const char* dir,
const char* filename,
const char* data, uint32 length,
bool binary) {
8349 if (!dir || !filename || strlen(filename) == 0)
8352 char* fullname =
new char[strlen(dir) + strlen(filename) + 5];
8353 snprintf(fullname, strlen(dir) + strlen(filename) + 5,
"%s/%s", dir, filename);
8359bool AppendToAFile(
const char* filename,
const char* data, uint32 length,
bool binary) {
8360 if (!filename || strlen(filename) == 0)
8365 file = fopen(filename,
"ab");
8367 file = fopen(filename,
"a");
8371 int res = (int)fwrite(data, 1, length, file);
8373 return (res == length);
8377 if (!dir || !filename || strlen(filename) == 0)
8380 char* fullname =
new char[strlen(dir) + strlen(filename) + 5];
8381 snprintf(fullname, strlen(dir) + strlen(filename) + 5,
"%s/%s", dir, filename);
8392 if (!filename || strlen(filename) == 0)
8396 return (SetFileAttributes(filename, FILE_ATTRIBUTE_READONLY) != 0);
8398 return (SetFileAttributes(filename, FILE_ATTRIBUTE_NORMAL) != 0);
8401 return (chmod(filename,S_IREAD | S_IWRITE) != 0);
8403 return (chmod(filename,S_IREAD) == 0);
8405 return (chmod(filename,S_IWRITE) == 0);
8407 return (chmod(filename,0) == 0);
8411bool MoveAFile(
const char* oldfilename,
const char* newfilename,
bool force) {
8415 result = (MoveFileEx(oldfilename, newfilename, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != 0);
8417 result = (MoveFileEx(oldfilename, newfilename, MOVEFILE_COPY_ALLOWED) != 0);
8423 if (rename(oldfilename, newfilename) == 0)
8429 delete(newfilename);
8430 if (rename(oldfilename, newfilename) == 0)
8434 if (error == EXDEV) {
8435 if (
CopyAFile(newfilename, oldfilename)) {
8444bool MoveAFile(
const char* olddir,
const char* oldfilename,
const char* newdir,
const char* newfilename,
bool force) {
8445 if (!newdir || !newfilename || !strlen(newfilename) ||
8446 !olddir || !oldfilename || !strlen(oldfilename) )
8449 char* oldname =
new char[strlen(olddir) + strlen(oldfilename) + 5];
8450 snprintf(oldname, strlen(olddir) + strlen(oldfilename) + 5,
"%s/%s", olddir, oldfilename);
8451 char* newname =
new char[strlen(newdir) + strlen(newfilename) + 5];
8452 snprintf(newname, strlen(newdir) + strlen(newfilename) + 5,
"%s/%s", newdir, newfilename);
8453 bool res =
MoveAFile(newname, oldname, force);
8459bool CopyAFile(
const char* oldfilename,
const char* newfilename,
bool force) {
8462 return (CopyFile(oldfilename, newfilename,
FALSE) != 0);
8464 return (CopyFile(oldfilename, newfilename,
TRUE) != 0);
8472 char* data =
ReadAFile(oldfilename, size,
true);
8473 if (!data || !size) {
8483 if (!
WriteAFile(newfilename, data, size,
true)) {
8492bool CopyAFile(
const char* olddir,
const char* oldfilename,
const char* newdir,
const char* newfilename,
bool force) {
8493 if (!newdir || !newfilename || !strlen(newfilename) ||
8494 !olddir || !oldfilename || !strlen(oldfilename) )
8497 char* oldname =
new char[strlen(olddir) + strlen(oldfilename) + 5];
8498 snprintf(oldname, strlen(olddir) + strlen(oldfilename) + 5,
"%s/%s", olddir, oldfilename);
8499 char* newname =
new char[strlen(newdir) + strlen(newfilename) + 5];
8500 snprintf(newname, strlen(newdir) + strlen(newfilename) + 5,
"%s/%s", newdir, newfilename);
8501 bool res =
CopyAFile(newname, oldname, force);
8508 if (!dirname || strlen(dirname) == 0)
8521 if (CreateDirectory(dirname, NULL) != 0)
8526 if (mkdir(dirname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
8534 if (!dirname || strlen(dirname) == 0)
8545 if (DeleteFile(dirname) != 0)
8551 if (DeleteFile(dirname) != 0)
8557 if (unlink(dirname) == 0)
8563 if (unlink(dirname) == 0)
8573 if (RemoveDirectory(dirname) != 0)
8579 if (RemoveDirectory(dirname) != 0)
8585 if (rmdir(dirname) == 0)
8591 if (rmdir(dirname) == 0)
8601 if (!dirname || strlen(dirname) == 0)
8610 for (uint32 n = 0; n<count; n++) {
8628 for (uint32 n=0; n<size; n++) {
8629 if (str[n] == find) {
8641 len2 = (int)strlen(str2);
8645 len1 = (int)strlen(str1);
8647 return (strcmp(str1, str2) == 0) ? str1 : 0;
8648 else if (len1 - len2 < 0)
8651 strp = (
char*)(str1 + len1 - len2);
8652 while(strp != str1) {
8653 if(*strp == *str2) {
8654 if(strncmp(strp,str2,len2)==0)
8666 len2 = (int)strlen(str2);
8670 len1 = (int)strlen(str1);
8672 return (
stricmp(str1, str2) == 0) ? str1 : 0;
8673 else if (len1 - len2 < 0)
8676 strp = (
char*)(str1 + len1 - len2);
8677 while(strp != str1) {
8678 if(*strp == *str2) {
8689 return (
laststristr(str, end) == str + strlen(str) - strlen(end));
8691 return (
laststrstr(str, end) == str + strlen(str) - strlen(end));
8696 return (
stristr(str, start) == str);
8698 return (strstr(str, start) == str);
8703 std::string name = filename;
8704 std::string::size_type p1 = name.find_last_of(
'/');
8705 std::string::size_type p2 = name.find_last_of(
'\\');
8706 if (p1 == std::string::npos) {
8707 if (p2 == std::string::npos)
8710 return name.substr(0, p2 + 1);
8712 else if (p2 == std::string::npos)
8713 return name.substr(0, p1 + 1);
8715 return name.substr(0, (p1 > p2) ? p1 + 1 : p2 + 1);
8719 std::string name = filename;
8720 std::string::size_type p1 = name.find_last_of(
'/');
8721 std::string::size_type p2 = name.find_last_of(
'\\');
8722 if (p1 == std::string::npos) {
8723 if (p2 == std::string::npos)
8726 return filename + p2 + 1;
8728 else if (p2 == std::string::npos)
8729 return filename + p1 + 1;
8731 return (p1 > p2) ? filename + p1 + 1 : filename + p2 + 1;
8736 char cCurrentPath[FILENAME_MAX];
8742 cCurrentPath[
sizeof(cCurrentPath) - 1] =
'\0';
8744 return cCurrentPath;
8747char*
GetFileList(
const char* dirname,
const char* ext, uint32& count,
bool fullpath, uint32 maxNameLen) {
8752 uint32 extlen = (ext == NULL) ? 0 : (uint32)strlen(ext);
8753 struct dirent* direntry = NULL;
8755 uint32 tempMaxCount = 50;
8756 uint32 len = (maxNameLen+1)*tempMaxCount;
8757 char* result =
new char[len];
8760 uint32 dirnamelen = (uint32)strlen(dirname);
8761 bool dirslash = (*(dirname + dirnamelen - 1) ==
'/') || (*(dirname + dirnamelen - 1) ==
'\\');
8769 if (direntry->
d_name[0] !=
'\0') {
8771 if ( !strcmp(direntry->
d_name,
".") || !strcmp(direntry->
d_name,
"..") ) {
8782 memset(dst+dirnamelen,
'/', 1);
8792 if (count >= tempMaxCount) {
8794 tmp =
new char[len*2];
8795 memcpy(tmp, result, len);
8819 struct stat statbuf;
8835 if ((fd = _open(filename, O_RDONLY)) == -1) {
8854 result = fstat(fd, &statbuf);
8865 info.
size = statbuf.st_size;
8866 info.
isDirectory = ((statbuf.st_mode & S_IFDIR) != 0);
8872 info.
isReadable = ((statbuf.st_mode & _S_IREAD) != 0);
8873 info.
isWritable = ((statbuf.st_mode & _S_IWRITE) != 0);
8874 info.
isExecutable = ((statbuf.st_mode & _S_IEXEC) != 0);
8876 info.
isReadable = ((statbuf.st_mode & S_IRUSR) != 0);
8877 info.
isWritable = ((statbuf.st_mode & S_IWUSR) != 0);
8878 info.
isExecutable = ((statbuf.st_mode & S_IXUSR) != 0);
8888 if (!ascii || (start >= end) || (!(len = (uint32)strlen(ascii))) ) {
8895 copy =
new char[end - start + 2];
8896 memcpy(copy, ascii + start,
8898 copy[end - start + 1] = 0;
8905 if (!ascii || (start > end))
return false;
8906 uint32 len = (uint32)strlen(ascii);
8907 uint32 stop = end ? end+1 : len;
8908 if (stop > len) stop = len;
8909 for (uint32 n=start; n<stop; n++) {
8910 if (( ascii[n] <
'0' || ascii[n] >
'9') && ascii[n] !=
'.')
8917 if (!ascii || (start > end))
return false;
8920 return _strtoi64(ascii + start, NULL, 10);
8922 return strtoll(ascii + start, NULL, 10);
8926 int64 val = _strtoi64(copy, NULL, 10);
8928 int64 val = strtoll(copy, NULL, 10);
8935 if (!ascii || (start > end))
return false;
8938 return _strtoui64(ascii + start, NULL, 10);
8940 return strtoull(ascii + start, NULL, 10);
8944 uint64 val = _strtoui64(copy, NULL, 10);
8946 uint64 val = strtoull(copy, NULL, 10);
8953 if (!ascii || (start > end))
return false;
8956 return _strtoui64(ascii + start, NULL, 16);
8958 return strtoull(ascii + start, NULL, 16);
8962 uint64 val = _strtoui64(copy, NULL, 16);
8964 uint64 val = strtoull(copy, NULL, 16);
8971 if (!ascii || (start > end))
return false;
8973 return (int32)strtol(ascii + start, NULL, 10);
8975 int32 val = (int32)strtol(copy, NULL, 10);
8981 if (!ascii || (start > end))
return false;
8983 return (uint32)strtoul(ascii + start, NULL, 10);
8985 uint32 val = (uint32)strtoul(copy, NULL, 10);
8991 if (!ascii || (start > end))
return false;
8993 return (uint32)strtoul(ascii + start, NULL, 16);
8995 uint32 val = (uint32)strtoul(copy, NULL, 16);
9001 if (!ascii || (start > end))
return false;
9003 return strtod(ascii + start, NULL);
9005 float64 val = strtod(copy, NULL);
9012 bool isEscaped =
false;
9013 char* tmp =
new char[5];
9015 std::ostringstream o;
9016 std::string::iterator c;
9017 for (c = str.begin(); c != str.end(); c++) {
9020 case '"': o <<
"\"";
break;
9021 case '\\': o <<
"\\";
break;
9022 case 'b': o <<
"\b";
break;
9023 case 'f': o <<
"\f";
break;
9024 case 'n': o <<
"\n";
break;
9025 case 'r': o <<
"\r";
break;
9026 case 't': o <<
"\t";
break;
9029 tmp[0] = (uint8)(*c++);
9030 tmp[1] = (uint8)(*c++);
9031 tmp[2] = (uint8)(*c++);
9032 tmp[3] = (uint8)(*c);
9033 o << (char) strtol(tmp, NULL, 16);
9041 case '\\': isEscaped =
true;
break;
9051 std::ostringstream o;
9052 std::string::iterator c;
9053 for (c = str.begin(); c != str.end(); c++) {
9055 case '"': o <<
"\\\"";
break;
9056 case '\\': o <<
"\\\\";
break;
9057 case '\b': o <<
"\\b";
break;
9058 case '\f': o <<
"\\f";
break;
9059 case '\n': o <<
"\\n";
break;
9060 case '\r': o <<
"\\r";
break;
9061 case '\t': o <<
"\\t";
break;
9063 if (
'\x00' <= *c && *c <=
'\x1f') {
9065 << std::hex << std::setw(4) << std::setfill(
'0') << (int)*c;
9127 srand( seedvalue ? seedvalue : (uint32)
GetTimeNow());
9134 double t = (1.0/((RAND_MAX + 1.0)*(RAND_MAX + 1.0)*(RAND_MAX + 1.0)));
9136 d = (rand () * ((RAND_MAX + 1.0) * (RAND_MAX + 1.0))
9137 + rand () * (RAND_MAX + 1.0)
9161 uint64 n = (uint64)(r/interval);
9162 double l = r - (n*interval);
9163 if (l >= (0.5*interval))
9164 return from + (n*interval);
9166 return from + ((n+1)*interval);
9170 return (int64)roundl(
RandomValue((
double)from, (
double)to));
9181 double mb = kb*1024;
9182 double gb = mb*1024;
9183 double tb = gb*1024;
9185 char *tmp =
new char[64];
9188 snprintf(tmp, 64,
"%.2f B", val);
9189 else if (val < 512*kb) {
9191 snprintf(tmp, 64,
"%.2f KB", val);
9193 else if (val < 512*mb) {
9195 snprintf(tmp, 64,
"%.2f MB", val);
9197 else if (val < 512*gb) {
9199 snprintf(tmp, 64,
"%.2f GB", val);
9203 snprintf(tmp, 64,
"%.2f TB", val);
9206 std::string result = tmp;
9218 double mb = kb*1024;
9219 double gb = mb*1024;
9220 double tb = gb*1024;
9222 char *tmp =
new char[64];
9223 char *end =
new char[64];
9226 double maximum = ((val1 > val2) ? val1 : val2);
9228 if (maximum < 512) {
9232 else if (maximum < 512*kb) {
9236 else if (maximum < 512*mb) {
9240 else if (maximum < 512*gb) {
9248 snprintf(tmp, 64,
"%.2f / %.2f %s", ((
double)val1)/val, ((
double)val2)/val, (
char*) end);
9250 std::string result = tmp;
9262 char *tmp =
new char[64];
9263 snprintf(tmp, 64,
"%s/sec", (
char*)
BytifySize(val).c_str());
9264 std::string result = tmp;
9274 char *tmp =
new char[64];
9275 snprintf(tmp, 64,
"%s/sec", (
char*)
BytifySizes(val1, val2).c_str());
9276 std::string result = tmp;
9290 HKEY hKeyRoot, hKey;
9291 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9293 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
9294 if (err != ERROR_SUCCESS)
9297 DWORD dwType = REG_DWORD;
9299 DWORD dwSize =
sizeof(numVal);
9301 err = RegQueryValueEx(hKey, entry, NULL, &dwType, (LPBYTE)&numVal, &dwSize);
9303 if (err != ERROR_SUCCESS)
9309 HKEY hKeyRoot, hKey;
9310 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9312 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
9313 if (err != ERROR_SUCCESS)
9316 DWORD dwType = REG_QWORD;
9318 DWORD dwSize =
sizeof(numVal);
9320 err = RegQueryValueEx(hKey, entry, NULL, &dwType, (LPBYTE)&numVal, &dwSize);
9322 if (err != ERROR_SUCCESS)
9328 HKEY hKeyRoot, hKey;
9329 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9331 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
9332 if (err != ERROR_SUCCESS) {
9336 DWORD dwType = REG_SZ;
9337 DWORD dwSize = 4096;
9338 char* lszValue =
new char[dwSize];
9340 err = RegQueryValueEx(hKey, entry, NULL, &dwType, (LPBYTE)lszValue, &dwSize);
9342 if (err != ERROR_SUCCESS) {
9347 std::string val = lszValue;
9353 DWORD dwDisposition;
9354 HKEY hKeyRoot, hKey;
9355 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9357 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_WRITE | KEY_WOW64_64KEY, &hKey);
9358 if (err != ERROR_SUCCESS) {
9359 err = RegCreateKeyEx(hKeyRoot, keySubName.c_str(), 0, NULL, 0, KEY_WRITE | KEY_WOW64_64KEY, NULL, &hKey, &dwDisposition);
9360 if (err != ERROR_SUCCESS)
9364 DWORD dwType = REG_DWORD;
9365 err = RegSetValueEx(hKey, entry, 0, dwType, (
const BYTE*)&value,
sizeof(value));
9367 return (err == ERROR_SUCCESS);
9371 DWORD dwDisposition;
9372 HKEY hKeyRoot, hKey;
9373 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9375 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_WRITE | KEY_WOW64_64KEY, &hKey);
9376 if (err != ERROR_SUCCESS) {
9377 err = RegCreateKeyEx(hKeyRoot, keySubName.c_str(), 0, NULL, 0, KEY_WRITE | KEY_WOW64_64KEY, NULL, &hKey, &dwDisposition);
9378 if (err != ERROR_SUCCESS)
9382 DWORD dwType = REG_QWORD;
9383 err = RegSetValueEx(hKey, entry, 0, dwType, (
const BYTE*)&value,
sizeof(value));
9385 return (err == ERROR_SUCCESS);
9389 DWORD dwDisposition;
9390 HKEY hKeyRoot, hKey;
9391 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9393 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_WRITE | KEY_WOW64_64KEY, &hKey);
9394 if (err != ERROR_SUCCESS) {
9395 err = RegCreateKeyEx(hKeyRoot, keySubName.c_str(), 0, NULL, 0, KEY_WRITE | KEY_WOW64_64KEY, NULL, &hKey, &dwDisposition);
9396 if (err != ERROR_SUCCESS)
9400 DWORD dwType = REG_SZ;
9401 DWORD dwSize = 4096;
9403 err = RegSetValueEx(hKey, entry, 0, dwType, (LPBYTE)value, (DWORD)(strlen(value) + 1));
9405 return (err == ERROR_SUCCESS);
9409 HKEY hKeyRoot, hKey;
9410 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9412 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_SET_VALUE | KEY_WOW64_64KEY, &hKey);
9413 if (err != ERROR_SUCCESS)
9417 err = RegDeleteValue(hKey, entry);
9418 return (err == ERROR_SUCCESS);
9425 std::string keySubName = GetRegistryKeyInfo(entry, hKeyRoot);
9426 uint32 err = RegDeleteKeyEx(hKeyRoot, keySubName.c_str(), KEY_WOW64_64KEY, 0);
9427 return (err == ERROR_SUCCESS);
9431 if (!key || !strlen(key))
9436 std::string keySubName = GetRegistryKeyInfo(root, hKeyRoot);
9437 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hKey);
9438 if (err != ERROR_SUCCESS)
9441 err = RegDeleteTree(hKey, key);
9442 return (err == ERROR_SUCCESS);
9454 DWORD dwDisposition;
9461 std::string keySubName = GetRegistryKeyInfo(entry, hKeyRoot);
9462 std::string keySubNewName = GetRegistryKeyInfo(newName, hKeyNewRoot);
9464 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
9465 if (err != ERROR_SUCCESS)
9468 err = RegCreateKeyEx(hKeyNewRoot, keySubNewName.c_str(), 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, &hKeyNew, &dwDisposition);
9469 if (err != ERROR_SUCCESS) {
9474 err = RegCopyTree(hKey, NULL, hKeyNew);
9477 RegCloseKey(hKeyNew);
9479 if (err != ERROR_SUCCESS) {
9480 RegDeleteKeyEx(hKeyNewRoot, keySubNewName.c_str(), KEY_WOW64_64KEY, 0);
9506std::string GetRegistryKeyInfo(
const char* key, HKEY &hKeyRoot) {
9509 if (path.size() < 2)
return false;
9510 if (
stristr(path.at(0).c_str(),
"HKEY_CLASSES_ROOT"))
9511 hKeyRoot = HKEY_CLASSES_ROOT;
9512 else if (
stristr(path.at(0).c_str(),
"HKEY_CURRENT_USER"))
9513 hKeyRoot = HKEY_CURRENT_USER;
9514 else if (
stristr(path.at(0).c_str(),
"HKEY_LOCAL_MACHINE"))
9515 hKeyRoot = HKEY_LOCAL_MACHINE;
9516 else if (
stristr(path.at(0).c_str(),
"HKEY_USERS"))
9517 hKeyRoot = HKEY_USERS;
9521std::string GetRegistryParentKeyInfo(
const char* key, HKEY &hKeyRoot) {
9524 if (path.size() < 2)
return false;
9525 if (
stristr(path.at(0).c_str(),
"HKEY_CLASSES_ROOT"))
9526 hKeyRoot = HKEY_CLASSES_ROOT;
9527 else if (
stristr(path.at(0).c_str(),
"HKEY_CURRENT_USER"))
9528 hKeyRoot = HKEY_CURRENT_USER;
9529 else if (
stristr(path.at(0).c_str(),
"HKEY_LOCAL_MACHINE"))
9530 hKeyRoot = HKEY_LOCAL_MACHINE;
9531 else if (
stristr(path.at(0).c_str(),
"HKEY_USERS"))
9532 hKeyRoot = HKEY_USERS;
9563 "Bitfield slot allocation: SetBit/SetBitN, first-free and last-occupied searches",
"util");
9565 "Timer scheduling and trigger delivery via waitForTimer",
"util");
9567 "ProbeProcessWait: stdin-blocked child detected, busy child not flagged, cpuTimeMs grows",
"util");
HTML/URL helper utilities: entity encoding/decoding, MIME type lookup and URL component parsing.
#define PROC_ERROR
Error state.
Object type ids used to tag and verify every binary structure in CMSDK memory.
#define DATAMESSAGEINFOID
Process-wide thread registry and lifecycle manager: the concurrency core of CMSDK.
Small, dependency-free unit test harness used by all CMSDK object tests.
Cross-platform utility toolbox for CMSDK: threading, synchronization, shared memory,...
#define thread_ret_val(ret)
#define THREAD_STATS_ADHOC
#define THREAD_FUNCTION_CALL
THREAD_RET(* THREAD_FUNCTION)(void *)
#define THREAD_STATS_AUTO
RAII guard whose single static instance triggers global utility cleanup at program exit.
CleanShutdown()
Default constructor; no side effects.
~CleanShutdown()
Destroys all lazily-created global utility maps via ClearUtilsMaps().
Callback interface for receiving log entries produced through LogSystem.
Process-wide singleton logging hub with per-topic verbosity/debug levels.
static bool SetLogFileOutput(const char *logfile, bool printOut=true)
Direct log output to a file.
static bool SetLogReceiver(LogReceiver *rec)
Register a receiver that gets every accepted LogEntry.
static bool LogSystemPrint(uint32 source, uint8 subject, uint8 level, const char *formatstring,...)
printf-style informational logging (usually invoked via the LogPrint macro).
static bool LogSystemDebug(uint32 source, uint8 subject, uint8 level, const char *formatstring,...)
printf-style debug logging (usually invoked via the LogDebug macro); same parameters as LogSystemPrin...
static LogSystem * LogSingleton
Lazily-created global instance used by all static functions.
static bool SetLogLevelDebug(uint8 level)
Set the debug level threshold for all topics.
static bool SetLogLevelVerbose(uint8 level)
Set the verbose (print) level threshold for all topics.
static bool Shutdown()
Terminate all managed threads, then destroy the singleton.
static UnitTestRunner & instance()
Access the singleton (created on first use).
void registerTest(const char *name, UnitTestFunc func, const char *description="", const char *category="", bool inDefaultRun=true)
Register a test with the runner.
Singleton snapshot of the parsed process command line (set via SetCommandLine()).
static CommandLineInfo * CommandLineInfoSingleton
Auto-reset notification event (condition variable style), optionally named for cross-process use.
bool waitNext()
Block until the next signal() occurs.
Event()
Create an anonymous, process-local event.
bool signal()
Wake all threads currently waiting on this event.
Thin RAII wrapper around a dynamically loaded library (LoadLibrary / dlopen).
LibraryFunction getFunction(const char *funcName)
Resolve an exported function.
static std::string patchLibraryFilename(const char *filename, const char *path=NULL)
Normalize a library name into a platform filename (adds lib prefix / .dll, .so, .dylib suffix and opt...
bool load(const char *filename)
Load a library.
Recursive mutual-exclusion lock, optionally named for cross-process use.
Mutex()
Create an anonymous, process-local mutex.
void setCancelSafe(bool on)
Make this mutex cancellation-safe (POSIX only; no-op on Windows).
bool leave()
Release the mutex.
bool enter()
Block until the mutex is acquired.
Counting semaphore, optionally named for cross-process use.
Semaphore(uint32 maxCount=100)
Create an anonymous semaphore.
bool signal()
Increment (release) the semaphore, waking one waiter.
bool wait()
Block until the semaphore can be decremented.
Multiplexing timer: schedule many periodic timers and consume their expiries from one queue.
bool addTimer(uint32 id, uint32 interval, uint64 start=0, uint64 end=0)
Register a periodic timer.
static std::map< uint32, Timer * > * timers
Global registry mapping globalID to live Timer instances, used by the OS callbacks.
bool triggerTimer(uint32 id)
Manually inject an expiry for timer id, as if it had fired now.
bool waitForTimer(uint32 timeout, uint32 &id, uint64 &time)
Wait for the next expiry of any registered timer.
bool removeTimer(uint32 id)
Unregister a timer and cancel its OS timer.
uint64 FTime2PsyTime(uint64 t)
Convert an ftime-style value (ms since Unix epoch) to a PsyTime µs timestamp.
uint64 GetTimeNow()
Return the current absolute time (µs since year 0) according to the TMC.
std::string PrintTimeNowString(bool local=true, bool us=true, bool ms=true)
Format GetTimeNow().
int32 GetTimeAgeMS(uint64 t)
Age of a timestamp relative to now, in milliseconds.
bool UnitTest_Utils()
Aggregate self test for miscellaneous utils functionality.
int64 AtomicDecrement64(int64 volatile &v)
Atomically decrement a 64-bit value.
bool ResizeProcessTerminal(uint32 proc, uint16 cols, uint16 rows)
Resize the pseudo-terminal (TIOCSWINSZ + SIGWINCH to the child's group).
uint32 NewProcess(const char *cmdline, const char *initdir=NULL, const char *title=NULL, int16 x=-1, int16 y=-1, int16 w=-1, int16 h=-1)
Launch a detached child process.
bool SetSharedSystemInstance(uint32 inst)
Set the instance number used to namespace shared OS objects, allowing several independent CMSDK syste...
static std::map< uint32, ProcessData * > * ProcessInformationMap
uint32 GetThreadStatColAbility()
Report this platform's capability for per-thread CPU statistics collection.
void ReleaseProcessCapture(uint32 proc)
POSIX only: release the captured stdout/stderr read-pipes recorded for a child by NewProcessEx(captur...
bool WaitForThreadToFinish(ThreadHandle hThread, uint32 timeoutMS=0)
Join a thread.
bool SignalSemaphore(const char *name)
Signal a named global semaphore.
bool GetThreadPriority(ThreadHandle hThread, uint16 priority)
Query a thread's scheduling priority.
std::pair< std::string, Mutex * > SharedMemoryMutexMapPair
int FromOSPriority(int pri)
Map a native OS priority back to the CMSDK priority scale.
bool CloseProcessInput(uint32 proc)
Close a child's stdin, delivering EOF (T1.1 step 2.7c).
bool EndProcess(uint32 proc)
Forcibly terminate a child process.
std::pair< std::string, Semaphore * > SharedMemorySemaphoreMapPair
static Mutex * SharedMemorySemaphoreMapMutex
bool GetLastOccupiedBitLoc(const char *bitfield, uint32 bytesize, uint32 &loc)
Find the highest set (occupied) bit.
const char * laststrstr(const char *str1, const char *str2)
Find the last occurrence of str2 in str1.
std::pair< std::string, Event * > SharedMemoryEventMapPair
bool DestroyEvent(const char *name)
Destroy a named global event.
bool WaitForSemaphore(const char *name, uint32 ms, bool autocreate=true)
Wait on a named global semaphore.
static SharedMemoryFileHandleMapType * SharedMemoryFileHandleMap
bool TextStartsWith(const char *str, const char *start, bool caseSensitive=true)
Test whether str starts with start.
bool Sleep(uint32 ms)
Suspend the calling thread.
bool SetThreadPriority(ThreadHandle hThread, uint16 priority)
Set a thread's scheduling priority.
bool ReadProcessTerminal(uint32 proc, std::string &out, bool &eofOut)
Non-blocking read of the merged terminal stream.
bool GetProcAndOSCPUUsage(double &procPercentUse, double &osPercentUse, uint64 &prevOSTicks, uint64 &prevOSIdleTicks, uint64 &prevProcTicks)
Sample CPU usage of this process and of the whole OS since the previous call.
bool PauseThread(ThreadHandle hThread)
Suspend a thread's execution.
uint32 NewProcessTerminal(const char *cmdline, const char *initdir, const std::map< std::string, std::string > *env, uint16 cols=0, uint16 rows=0)
Launch a child on a new pseudo-terminal (POSIX: posix_openpt + fork; child setsid() + TIOCSCTTY so it...
static std::map< std::string, Event * > * SharedMemoryEventMap
bool MoveConsoleWindow(int32 x=-1, int32 y=-1, int32 w=-1, int32 h=-1)
Move/resize the console window.
bool WriteProcessTerminal(uint32 proc, const char *data, uint32 len)
Write bytes to the child's terminal input (its stdin).
bool IsThreadRunning(ThreadHandle hThread)
Check whether a thread is still alive.
bool CreateThread(THREAD_FUNCTION func, void *args, ThreadHandle &thread, uint32 &osID)
Start a new OS thread.
int32 AtomicDecrement32(int32 volatile &v)
Atomically decrement a 32-bit value.
uint32 NewProcessEx(const char *cmdline, const char *initdir, const char *title, const std::map< std::string, std::string > *env, bool captureOutput, bool ignoreOutput, bool newProcessGroup, int posixParentDeathSig=0, bool posixUseShell=false)
Launch a child with environment overrides and optional output capture.
static std::map< uint32, DrumBeatInfo > * DrumBeatMap
bool SignalThread(ThreadHandle hThread, int32 signal)
Send a signal to a thread (POSIX pthread_kill; limited emulation on Windows).
bool BlockShutdownSignals()
Block the graceful-shutdown signals (SIGINT, SIGTERM, SIGHUP) on the CALLING thread.
bool UnitTest_ProbeProcessWait()
char * OpenSharedMemorySegment(const char *name, uint64 size)
Open and map an existing named shared memory segment.
int64 AtomicIncrement64(int64 volatile &v)
Atomically increment a 64-bit value.
uint32 GetSharedSystemInstance()
Get the current shared-system instance number.
bool StopDrumBeat(uint32 id)
Stop a running drum beat without destroying it.
bool EnterMutex(const char *name, uint32 ms, bool autocreate=true)
Acquire a named global mutex, creating it on first use.
const char * laststristr(const char *str1, const char *str2)
Case-insensitive laststrstr().
bool ProbeProcessWait(uint32 pid, ProcessWaitInfo &out)
Probe whether a child process (group) appears blocked reading stdin (fd 0).
static Mutex * SharedMemoryMutexMapMutex
#define SharedMemoryFileHandleMapType
bool CreateDrumBeat(uint32 id, uint32 interval, DrumBeatFunc func, bool autostart=false)
Create a periodic timer ("drum beat") that calls func every interval ms.
bool ReapThread(ThreadHandle &hThread)
std::string PrintProgramTrace(uint32 startLine=0, uint32 endLine=0)
Format the current call stack as printable text.
uint8 GetProcessStatus(uint32 proc, int &returncode)
Poll a child started with NewProcess().
bool(* DrumBeatFunc)(uint32 id, uint32 count)
Callback invoked on every drum-beat tick.
static Mutex * SharedMemoryEventMapMutex
Semaphore * GetSemaphore(const char *name, bool autocreate=true)
Look up (and optionally create) a named semaphore in the global registry.
bool LeaveMutex(const char *name)
Release a named global mutex previously acquired with EnterMutex().
int RunOSCommand(const char *cmdline, const char *initdir, uint32 timeout, std::string &stdoutString, std::string &stderrString)
Run a command synchronously and capture its output.
char * CreateSharedMemorySegment(const char *name, uint64 size, bool force=false)
Create a named shared memory segment and map it into this process.
std::string PrintBitFieldString(const char *bitfield, uint32 bytesize, uint32 size, const char *title)
Like GetBitFieldAsString() but prefixed with title and formatted for printing.
std::string GetBitFieldAsString(const char *bitfield, uint32 bytesize, uint32 size)
Render the first size bits as a '0'/'1' string, for debugging.
uint8 WaitForProcess(uint32 proc, uint32 timeout, int &returncode)
Wait for a child to exit.
uint32 GetLocalProcessID()
Get the OS process id of the current process.
bool EndDrumBeat(uint32 id)
Destroy a drum beat and release its OS timer.
bool DestroySemaphore(const char *name)
Destroy a named global semaphore.
bool CloseSharedMemorySegment(char *data, uint64 size)
Unmap a segment previously created/opened here.
bool TerminateThread(ThreadHandle hThread)
Forcibly kill a thread.
bool GetFirstFreeBitLocN(const char *bitfield, uint32 bytesize, uint32 num, uint32 &loc)
Find the first run of num consecutive 0 bits.
bool StartSignalThread(ShutdownSignalCallback cb)
Start the dedicated signal-handling thread (POSIX only).
bool GetCurrentThreadUniqueID(uint32 &tid)
Get a process-unique id for the calling thread.
int32 AtomicIncrement32(int32 volatile &v)
Atomically increment a 32-bit value.
bool GetDesktopSize(uint32 &width, uint32 &height)
Get the primary desktop resolution.
bool CheckForThreadFinished(ThreadHandle hThread)
Non-blocking check whether a thread has terminated.
void(* ShutdownSignalCallback)(int sig, int count)
Callback invoked (on the dedicated signal thread) when a graceful-shutdown signal is caught.
bool DestroyMutex(const char *name)
Destroy a named global mutex and remove it from the registry.
bool ContinueThread(ThreadHandle hThread)
Resume a thread paused with PauseThread().
const char * stristr(const char *str, const char *substr, uint32 len=0)
Case-insensitive strstr.
void CloseProcessTerminal(uint32 proc)
Close the master side (terminal hangup: the child's foreground group gets SIGHUP and any blocked term...
std::list< std::string > GetProgramTrace()
Capture the current call stack.
uint64 hton64(const uint64_t *input)
Convert a 64-bit value from host to network byte order.
static uint16 SharedSystemInstance
static void TimerCallback(int sig, siginfo_t *siginfo, void *context)
POSIX signal-based timer callback trampoline (SIGEV_SIGNAL); routes the expiry into the owning Timer'...
void PrintBinary(void *p, uint32 size, bool asInt, const char *title)
Hex/decimal dump a memory region to stdout for debugging.
static std::map< std::string, Mutex * > * SharedMemoryMutexMap
bool GetFirstFreeBitLoc(const char *bitfield, uint32 bytesize, uint32 &loc)
Find the first 0 (free) bit.
bool SignalEvent(const char *name)
Signal a named global event.
bool WriteProcessInput(uint32 proc, const char *data, uint32 len)
Write to the stdin of a child launched with captureOutput=true (T1.1 step 2.7c).
bool GetCPUTicks(ThreadHandle hThread, uint64 &ticks)
Get accumulated CPU time of a specific thread.
bool GetNextLineEnd(const char *str, uint32 size, uint32 &len, uint32 &crSize)
Find the end of the current line.
bool GetBit(uint32 loc, const char *bitfield, uint32 bytesize, bit &val)
Read bit loc.
uint64 ntoh64(const uint64 *input)
Convert a 64-bit value from network to host byte order.
bool GetProcessCPUTicks(uint64 &ticks)
Get accumulated CPU time of the current process.
bool ReadProcessOutput(uint32 proc, std::string &out, std::string &err)
Read any pending captured stdout/stderr from a child launched with captureOutput=true.
int ToOSPriority(int pri)
Map a CMSDK priority value to the platform's native priority scale.
static std::map< std::string, Semaphore * > * SharedMemorySemaphoreMap
bool StopSignalThread()
Stop the dedicated signal thread and join it.
bool SendProcessBreak(uint32 proc, int sig)
Attempt a graceful stop: POSIX sends the given signal; Windows posts a CTRL_BREAK to the child's proc...
bool SetBitN(uint32 loc, uint32 num, bit value, char *bitfield, uint32 bytesize)
Set num consecutive bits starting at loc to value.
bool Reset32BitField(char *bitfield, uint32 bytesize)
Zero the whole bitfield, marking every bit as free.
bool StartDrumBeat(uint32 id)
Start (or resume) a previously created drum beat.
bool TextEndsWith(const char *str, const char *end, bool caseSensitive=true)
Test whether str ends with end.
bool UnitTest_Timer()
Self test for the Timer class.
bool SetBit(uint32 loc, bit value, char *bitfield, uint32 bytesize)
Set bit loc to value.
bool GetCurrentThread(ThreadHandle &thread)
Get the handle of the calling thread.
bool RenameConsoleWindow(const char *name, bool prepend=false)
Set the console window title.
bool TryReapThread(ThreadHandle &hThread)
bool UtilsTest()
Run the built-in self test of the utils module.
uint32 Calc32BitFieldSize(uint32 bitsize)
Compute the byte size needed for a bitfield of bitsize bits, rounded up to a 32-bit boundary.
uint32 TextReplaceCharsInPlace(char *str, uint32 size, char find, char replace)
Replace every occurrence of a character, in place.
uint32 strcpyavail(char *dst, const char *src, uint32 maxlen, bool copyAvailable)
Bounded strcpy that always NUL-terminates.
void ClearStaleSharedSegments(uint16 port)
Remove stale OS shared-memory/semaphore objects left by a crashed node on this port.
std::pair< uint32, ProcessData * > Proc_Pair
bool GetOSCPUUsage(double &percentUse)
Get the instantaneous total OS CPU usage.
bool GetCurrentThreadOSID(uint32 &tid)
Get the OS-level id of the calling thread (gettid / GetCurrentThreadId).
std::string EncodeHTML(std::string str)
Encode a plain string for safe embedding in HTML (e.g.
void fail(const char *fmt,...)
Set an explanatory reason shown on the FAIL line.
void metric(const char *name, double value, const char *unit="", bool higherIsBetter=true)
Record a performance metric.
void detail(const char *fmt,...)
Verbose-only indented diagnostic line (shown only when verbose=1).
void progress(int percent, const char *action)
Report progress with a short description of the current action.
bool SeedRandomValues(uint32 seedvalue=0)
Seed the pseudo-random generator.
int GetLastOSErrorNumber()
Get the last OS error number (errno / GetLastError()).
static THREAD_RET THREAD_FUNCTION_CALL SignalThreadMain(THREAD_ARG arg)
std::string GetLastOSErrorMessage()
Get the last OS error as human-readable text.
static bool AnyCancelSafeMutexes()
std::vector< std::string > TextListBreakLines(const char *text, uint32 maxLineLength=80)
Word-wrap text into lines no longer than maxLineLength.
int8 CompareFloats(float64 a, float64 b)
Compare two doubles with epsilon tolerance.
uint32 * GetLocalIPAddresses(uint32 &count)
List all local IPv4 addresses.
std::string EncodeJSON(std::string str)
Escape text for embedding as a JSON string value.
unsigned char * Ascii2UTF16LE(const char *ascii, uint32 len, uint32 &size)
Convert 8-bit ASCII text to UTF-16LE (used for Windows wide APIs and some protocols).
uint64 GetProcessMemoryUsage()
Current resident memory usage of this process.
char ** SplitCommandline(const char *cmdline, int &argc)
Split a command line into a malloc'ed argv array.
uint64 ReadRegistryQWORD(const char *key, const char *entry)
Read a 64-bit registry value.
static std::map< uint32, int > * TerminalMasterMap
std::string GetCommandLineArg(uint16 n)
Get the n-th positional command line item.
bool CreateADir(const char *dirname)
Create a directory (parents included where supported).
std::string BytifyRates(double val1, double val2)
Format two byte rates as "x / y" with matching units.
bool CopyAFile(const char *oldfilename, const char *newfilename, bool force=false)
Copy a file.
bool DeleteFilesInADir(const char *dirname, bool force)
Delete all files inside a directory, leaving the directory itself.
uint32 GetCommandLineArgCount()
Number of positional command line items (excluding the executable).
uint16 GetCPUArchitecture()
CPU architecture id.
char OSLocalHostName[1024]
char OSArchitectureName[1024]
std::string ReadAFileString(std::string filename)
Read an entire file into a std::string.
static uint32 g_shutdownSignalCount
char * StringFormatVA(uint32 &size, const char *format, va_list args)
va_list core used by the other StringFormat overloads.
std::string TextUppercase(const char *text)
Convert to upper case (ASCII/current locale).
static std::condition_variable & gLaunchCv
int CRC32(const char *addr, uint32 length, int32 crc=0)
Compute (or continue) a CRC-32 checksum.
static pthread_mutex_t g_cancelSafeSetLock
bool WaitForSocketReadability(SOCKET s, int32 timeout)
Wait until a socket has data to read.
uint64 * GetLocalMACAddresses(uint32 &count)
List all local MAC addresses.
bool WaitForNextEvent(const char *name, uint32 ms, bool autocreate)
static volatile int g_cancelSafeCount
const char * GetSystemArchitecture()
Architecture name string, e.g.
std::string TextTrim(const char *text)
Strip leading and trailing whitespace.
std::string GetCommandLinePath()
Get the directory portion of the executable path.
bool HasCommandLineArg(const char *key, std::string &value)
Test for a 'key=value' argument without mutating the argument map.
bool SetSocketBlockingMode(SOCKET s)
Put a socket into blocking mode.
uint32 Ascii2Uint32(const char *ascii, uint32 start=0, uint32 end=0)
Parse an unsigned 32-bit decimal integer from a substring.
uint64 GetCPUSpeed()
Nominal CPU clock speed.
wchar_t ** SplitCommandlineW(const char *cmdline, int &argc)
Wide-character variant of SplitCommandline() (for Windows APIs).
std::string TextVectorConcat(std::vector< std::string >, const char *sep, bool allowEmpty=true)
Concatenate vector entries with sep.
bool AppendToAFile(const char *filename, const char *data, uint32 length, bool binary=false)
Append to a file, creating it if missing.
std::string TextIndent(const char *text, const char *indent)
Prefix every line of text with indent.
unsigned char Dec2Char(const char *str)
Parse up to three decimal digits into a byte.
char * GetFileList(const char *dirname, const char *ext, uint32 &count, bool fullpath, uint32 maxNameLen=256)
List files in a directory matching an extension.
bool GetNextAvailableLocalPort(uint16 lastPort, uint16 &nextPort)
Find the next free TCP port above lastPort.
static std::map< const void *, bool > * g_cancelSafeSet
static std::mutex & gLaunchMx
bool MoveAFile(const char *oldfilename, const char *newfilename, bool force=false)
Move/rename a file.
uint32 StringMultiReplace(std::string &text, std::map< std::string, std::string > &map, bool onlyFirst)
Apply many key→value replacements in one pass.
std::vector< std::string > TextListSplit(const char *text, const char *split, bool keepEmpty=true, bool autoTrim=false)
Split text on a separator.
bool IsTextNumeric(const char *ascii, uint32 start=0, uint32 end=0)
Test whether a (sub)string is a valid number.
uint16 GetCPUCount()
Number of logical CPU cores.
char * Uint2Ascii(uint64 value, char *result, uint16 size, uint8 base)
Render an unsigned integer as text in an arbitrary base.
std::map< std::string, std::string > TextMapSplit(const char *text, const char *outersplit, const char *innersplit)
Split "k=v<sep>k=v..." text into a map (later duplicates overwrite earlier ones).
uint64 GetPeakProcessMemoryUsage()
Peak resident memory usage of this process.
bool DeleteCommandline(char **argv, int argc)
Free an argv array produced by SplitCommandline().
uint32 AsciiHex2Uint32(const char *ascii, uint32 start=0, uint32 end=0)
Parse an unsigned 32-bit hexadecimal integer from a substring.
bool DeleteRegistryKey(const char *key)
Delete a (leaf) registry key.
bool GetLocalHostname(char *name, uint32 maxSize)
Local hostname into a caller buffer.
std::string TextUnindent(const char *text)
Remove one level of leading indentation from every line.
bool GetSystemOSVersion(uint16 &major, uint16 &minor, uint16 &build, char *text, uint16 textSize)
Detailed OS version.
uint32 StringScriptReplace(std::string &text, std::string name, std::list< std::map< std::string, std::string > > &list)
Expand a named repeating template block in text once per map in list, substituting each map's keys in...
std::string TextJoinXML(std::map< std::string, std::string > &map, const char *innernodeName, const char *outernodeName)
Serialize a map as XML, one innernodeName element per pair inside an outernodeName element.
bool SetCommandLine(int argc, char *argv[])
Parse and store the process command line for later retrieval by the Get/HasCommandLine* functions.
uint32 StringSingleReplace(std::string &text, std::string key, std::string value, bool onlyFirst)
Replace occurrences of key with value in text.
uint64 GetSystemMemorySize()
Total physical RAM installed.
uint32 ReadRegistryDWORD(const char *key, const char *entry)
Read a 32-bit registry value.
static bool TerminalMasterFind(uint32 proc, int &fd)
static ShutdownSignalCallback g_shutdownCallback
bool GetLocalMACAddress(uint64 &address)
Get the primary local MAC address.
bool WaitForSocketWriteability(SOCKET s, int32 timeout)
Wait until a socket can be written without blocking.
FileDetails GetFileDetails(const char *filename)
Stat a file.
double RandomValue()
Uniform random double in [0,1).
bool GetSocketError(int wsaError, char *errorString, uint16 errorStringMaxSize, bool *isRecoverable)
Translate a socket error code into text and classify it.
std::string GetCommandLineExecutableOnly()
Get just the executable filename without path.
static volatile sig_atomic_t g_signalThreadStop
std::multimap< std::string, std::string > TextMultiMapSplit(const char *text, const char *outersplit, const char *innersplit)
Split "k=v<sep>k=v..." text into a multimap (duplicate keys preserved).
bool RenameRegistryTree(const char *entry, const char *newName)
static bool ContainsPortToken(const char *name, const char *portstr, size_t plen)
bool GetLocalIPAddress(uint32 &address)
Get the primary local IPv4 address.
bool LookupHostname(uint32 address, char *name, uint32 maxSize)
Reverse-resolve an IPv4 address to a hostname.
char * TextSubstringCopy(const char *ascii, uint32 start, uint32 end)
Copy the substring [start,end) into a new NUL-terminated buffer.
bool LookupIPAddress(const char *name, uint32 &address)
Resolve a hostname to an IPv4 address.
static uint32 ClearSegmentsIn(const char *dir, const char *prefix, const char *portstr, size_t plen)
char * Int2Ascii(int64 value, char *result, uint16 size, uint8 base)
Render a signed integer as text in an arbitrary base.
std::string GetLocalHostnameString()
Local hostname as std::string.
static pid_t DoPosixForkExec(PosixLaunchRequest &r)
int32 Ascii2Int32(const char *ascii, uint32 start=0, uint32 end=0)
Parse a signed 32-bit decimal integer from a substring.
bool DoesAFileExist(const char *filename)
Test whether a regular file exists.
NetworkInterfaces * GetLocalInterfaces(uint32 &count)
Enumerate local network interfaces with address, MAC and names.
std::string TextTrimQuotes(const char *text)
Strip a single pair of surrounding quotes if present.
unsigned char Hex2Char(const char *str)
Parse two hex digits into a byte.
bool DeleteAFile(const char *filename, bool force)
Delete a file.
bool ChangeAFileAttr(const char *filename, bool read, bool write)
Change read/write permission attributes of a file.
static bool MutexIsCancelSafe(const void *m)
std::string BytifySize(double val)
Format a byte count with binary units, e.g.
std::string GetCommandLineExecutable()
Get the full executable path as invoked.
bool StringFormatInto(char *dst, uint32 maxsize, const char *format,...)
printf into a caller-supplied buffer with truncation.
std::vector< std::string > TextListSplitLines(const char *text, bool keepEmpty=true, bool autoTrim=false)
Split text into lines, handling both \n and \r\n.
bool WriteAFile(const char *filename, const char *data, uint32 length, bool binary=false)
Write (create/overwrite) a file.
std::string GetCurrentDir()
Current working directory.
std::string GetCommandLine()
Get the full original command line as one string.
bool CalcTimeout(struct timespec &timeout, uint32 ms)
static std::mutex gLaunchSerialMx
std::string ReadRegistryString(const char *key, const char *entry)
Read a string registry value.
std::vector< std::string > TextCommandlineSplit(const char *cmdline)
Split a command line into arguments, honouring quoting rules.
bool DoesADirExist(const char *dirname)
Test whether a directory exists.
bool DeleteRegistryEntry(const char *key, const char *entry)
Delete a single value from a key.
static bool gLauncherStarted
std::string StringFormat(const char *format,...)
printf into a std::string.
bool SetSocketNonBlockingMode(SOCKET s)
Put a socket into non-blocking mode.
bool DeleteADir(const char *dirname, bool force)
Delete a directory (recursively when force).
bool WriteRegistryQWORD(const char *key, const char *entry, uint64 value)
Write a 64-bit registry value.
char * ReadAFile(const char *filename, uint32 &length, bool binary=false)
Read an entire file into a new buffer.
static __thread int g_savedCancelState
uint64 Ascii2Uint64(const char *ascii, uint32 start=0, uint32 end=0)
Parse an unsigned 64-bit decimal integer from a substring.
uint64 AsciiHex2Uint64(const char *ascii, uint32 start=0, uint32 end=0)
Parse an unsigned 64-bit hexadecimal integer (with or without 0x) from a substring.
const char * GetFileBasename(const char *filename)
Filename portion of a path.
static PosixLaunchRequest * gLaunchReq
Library * OpenLibrary(const char *libName)
Load a library by name, applying platform filename conventions.
bool WriteRegistryString(const char *key, const char *entry, const char *value)
Write a string registry value.
static void DrumBeatCallback(union sigval p)
bool GetSystemMemoryUsage(uint64 &totalRAM, uint64 &freeRAM)
Query total and free physical memory.
static THREAD_RET THREAD_FUNCTION_CALL ProcessLauncherRun(THREAD_ARG)
int64 Ascii2Int64(const char *ascii, uint32 start=0, uint32 end=0)
Parse a signed 64-bit decimal integer from a substring.
static pid_t SubmitLaunchRequest(PosixLaunchRequest &req)
bool WriteRegistryDWORD(const char *key, const char *entry, uint32 value)
Write a 32-bit registry value (creates the key when needed).
std::string TextJoinJSON(std::map< std::string, std::string > &map)
Serialize a map as a JSON object (keys/values escaped).
bool CopyRegistryTree(const char *entry, const char *newName)
Recursively copy a registry subtree.
static bool g_signalThreadRunning
int(* LibraryFunction)()
Signature of a plain function exported from a dynamically loaded library.
bool DeleteRegistryTree(const char *root, const char *key)
Recursively delete a key and all subkeys.
std::string TextLowercase(const char *text)
Convert to lower case (ASCII/current locale).
std::string DecodeJSON(std::string str)
Unescape a JSON string value (\" \\ \n \t \uXXXX etc.).
std::string TextCapitalise(const char *text)
Capitalise the first letter of text.
const char * GetComputerName()
Get this machine's hostname.
std::string GetFilePath(const char *filename)
Directory portion of a path.
static void SignalShutdownSigset(sigset_t *set)
const char * GetSystemOSName()
OS name string, e.g.
std::string BytifySizes(double val1, double val2)
Format two byte counts as "x / y" with matching units.
bool IsLocalIPAddress(const char *addr)
Test whether a textual address refers to this machine (loopback or a local interface).
float64 Ascii2Float64(const char *ascii, uint32 start=0, uint32 end=0)
Parse a 64-bit float from a substring (decimal point, not locale dependent).
std::string TextJoin(std::vector< std::string > &list, const char *split, uint32 start=0, uint32 count=0)
Join vector elements with split.
static pthread_t g_signalThread
int64 RandomInt(int64 from=0, int64 to=100)
Uniform random integer in [from,to].
std::string BytifyRate(double val)
Format a byte rate, e.g.
CleanShutdown CleanShutdownInstance
struct dirent * readdir(DIR *)
DIR * opendir(const char *)
bool ClearUtilsMaps()
Free all lazily-allocated global registries (mutex/semaphore/event/shared-memory maps).
static bool Test_ProbeProcessWait()
uint32 CleanShutdownInstanceCount
void Register_Utils_Tests()
uint32 GetDataTypeID(const char *typeName)
Inverse of GetDataTypeName(): look up the numeric datatype id for a type name.
std::string GetDataTypeName(uint32 datatype)
Translate a CMSDK datatype id (e.g.
Wire/storage layout of one log record: fixed header immediately followed by the message text.
std::string toJSON()
Serialize the entry (header fields + text) as a JSON object string.
bool setText(char *text, uint32 len)
Copy len bytes of text into the payload area and update size.
const char * getText(uint32 &len)
Access the text payload stored after the header.
std::string toXML()
Serialize the entry as an XML fragment.
Bookkeeping record for one periodic "drum beat" timer.
Existence, type, permission and timestamp information for one file, as returned by GetFileDetails().
Description of one local network interface (IPv4 address, MAC and names).
char friendlyName[MAXKEYNAMELEN+1]
char name[MAXKEYNAMELEN+1]
const std::map< std::string, std::string > * env
POSIX capture bookkeeping for children started via NewProcessEx(captureOutput).
int errFD
Parent read-end of the child's stderr (-1 = not captured).
int outFD
Parent read-end of the child's stdout (-1 = not captured).
Snapshot from ProbeProcessWait(): is the child (group) alive, is it blocked reading stdin,...
uint64 cpuTimeMs
cumulative user+sys CPU across the process group, in ms
bool waitingStdin
blocked reading fd 0 (exact on Linux; best-effort composite elsewhere)
bool alive
process (or group) still exists
bool waitExact
true only when the OS reported the exact blocking syscall (Linux /proc/<pid>/syscall)
One scheduled entry inside a Timer: id, active window and platform timer handle.
A single timer expiry: which timer fired and when.