12 #include <linux/unistd.h> 16 #include <sys/resource.h> 17 #include <sys/syscall.h> 20 #include <sys/prctl.h> 24 static bool GetAbsTime(
struct timespec *Abstime,
int MillisecondsFromNow)
27 if (gettimeofday(&now, NULL) == 0) {
28 now.tv_sec += MillisecondsFromNow / 1000;
29 now.tv_usec += (MillisecondsFromNow % 1000) * 1000;
30 if (now.tv_usec >= 1000000) {
32 now.tv_usec -= 1000000;
34 Abstime->tv_sec = now.tv_sec;
35 Abstime->tv_nsec = now.tv_usec * 1000;
46 pthread_mutex_init(&
mutex, NULL);
47 pthread_cond_init(&
cond, NULL);
52 pthread_cond_broadcast(&
cond);
53 pthread_cond_destroy(&
cond);
54 pthread_mutex_destroy(&
mutex);
65 pthread_mutex_lock(&
mutex);
68 struct timespec abstime;
71 if (pthread_cond_timedwait(&
cond, &
mutex, &abstime) == ETIMEDOUT)
81 pthread_mutex_unlock(&
mutex);
87 pthread_mutex_lock(&
mutex);
89 pthread_cond_broadcast(&
cond);
90 pthread_mutex_unlock(&
mutex);
97 pthread_cond_init(&
cond, 0);
102 pthread_cond_broadcast(&
cond);
103 pthread_cond_destroy(&
cond);
109 int locked = Mutex.
locked;
122 struct timespec abstime;
124 int locked = Mutex.
locked;
127 if (pthread_cond_timedwait(&
cond, &Mutex.
mutex, &abstime) == ETIMEDOUT)
137 pthread_cond_broadcast(&
cond);
144 pthread_rwlockattr_t attr;
145 pthread_rwlockattr_init(&attr);
146 pthread_rwlockattr_setkind_np(&attr, PreferWriter ? PTHREAD_RWLOCK_PREFER_WRITER_NP : PTHREAD_RWLOCK_PREFER_READER_NP);
147 pthread_rwlock_init(&rwlock, &attr);
152 pthread_rwlock_destroy(&rwlock);
158 struct timespec abstime;
164 Result = TimeoutMs ? pthread_rwlock_timedwrlock(&rwlock, &abstime) : pthread_rwlock_wrlock(&rwlock);
166 Result = TimeoutMs ? pthread_rwlock_timedrdlock(&rwlock, &abstime) : pthread_rwlock_rdlock(&rwlock);
172 pthread_rwlock_unlock(&rwlock);
180 pthread_mutexattr_t attr;
181 pthread_mutexattr_init(&attr);
182 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
183 pthread_mutex_init(&
mutex, &attr);
188 pthread_mutex_destroy(&
mutex);
193 pthread_mutex_lock(&
mutex);
200 pthread_mutex_unlock(&
mutex);
209 active = running =
false;
214 SetDescription(
"%s", Description);
215 lowPriority = LowPriority;
226 if (setpriority(PRIO_PROCESS, 0, Priority) < 0)
232 if (syscall(SYS_ioprio_set, 1, 0, (Priority & 0xff) | (3 << 13)) < 0)
242 va_start(ap, Description);
254 if (prctl(PR_SET_NAME, Thread->
description, 0, 0, 0) < 0)
270 #define THREAD_STOP_TIMEOUT 3000 // ms to wait for a thread to stop before newly starting it 271 #define THREAD_STOP_SLEEP 30 // ms to sleep while waiting for a thread to stop 284 active = running =
true;
285 if (pthread_create(&childTid, NULL, (
void *(*) (
void *))&StartThread, (
void *)
this) == 0) {
286 pthread_detach(childTid);
290 active = running =
false;
311 if ((err = pthread_kill(childTid, 0)) != 0) {
315 active = running =
false;
326 if (active && WaitSeconds > -1) {
327 if (WaitSeconds > 0) {
328 for (time_t t0 = time(NULL) + WaitSeconds; time(NULL) < t0; ) {
333 esyslog(
"ERROR: %s thread %d won't end (waited %d seconds) - canceling it...", description ? description :
"", childThreadId, WaitSeconds);
335 pthread_cancel(childTid);
343 return syscall(__NR_gettid);
348 if (mainThreadId == 0)
349 mainThreadId = ThreadId();
351 esyslog(
"ERROR: attempt to set main thread id to %d while it already is %d", ThreadId(), mainThreadId);
371 if (Mutex && !
mutex) {
391 if (thread && locked)
397 if (Thread && !thread) {
472 if ((pid = fork()) < 0) {
479 const char *mode =
"w";
483 if (strcmp(Mode,
"r") == 0) {
488 if ((f = fdopen(fd[1 - iopipe], mode)) == NULL) {
490 close(fd[1 - iopipe]);
495 int iofd = STDOUT_FILENO;
496 if (strcmp(Mode,
"w") == 0) {
501 if (dup2(fd[1 - iopipe], iofd) == -1) {
503 close(fd[1 - iopipe]);
507 int MaxPossibleFileDescriptors = getdtablesize();
508 for (
int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++)
510 if (execl(
"/bin/sh",
"sh",
"-c", Command, NULL) == -1) {
512 close(fd[1 - iopipe]);
533 ret = waitpid(pid, &status, WNOHANG);
535 if (errno != EINTR && errno != ECHILD) {
549 else if (ret == -1 || !WIFEXITED(status))
563 if ((pid = fork()) < 0) {
570 if (waitpid(pid, &status, 0) < 0) {
582 pid_t sid = setsid();
586 int devnull = open(
"/dev/null", O_RDONLY);
587 if (devnull < 0 || dup2(devnull, 0) < 0)
590 int MaxPossibleFileDescriptors = getdtablesize();
591 for (
int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++)
593 if (execl(
"/bin/sh",
"sh",
"-c", Command, NULL) == -1) {
virtual void Action(void)=0
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
void SetDescription(const char *Description,...) __attribute__((format(printf
void Signal(void)
Signals a caller of Wait() that the condition it is waiting for is met.
static bool GetAbsTime(struct timespec *Abstime, int MillisecondsFromNow)
void SetPriority(int Priority)
cThreadLock(cThread *Thread=NULL)
#define THREAD_STOP_TIMEOUT
cRwLock(bool PreferWriter=false)
static cString static cString vsprintf(const char *fmt, va_list &ap)
cMutexLock(cMutex *Mutex=NULL)
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
static void * StartThread(cThread *Thread)
void bool Start(void)
Sets the description of this thread, which will be used when logging starting or stopping of the thre...
bool Open(const char *Command, const char *Mode)
#define THREAD_STOP_SLEEP
bool Lock(bool Write, int TimeoutMs=0)
bool Wait(int TimeoutMs=0)
Waits at most TimeoutMs milliseconds for a call to Signal(), or forever if TimeoutMs is 0...
static tThreadId ThreadId(void)
bool TimedWait(cMutex &Mutex, int TimeoutMs)
int SystemExec(const char *Command, bool Detached)
void Activate(void)
Activates the global I/O throttling mechanism.
void SetIOPriority(int Priority)
static void SetMainThreadId(void)
bool Active(void)
Checks whether the thread is still alive.
static bool Engaged(void)
Returns true if any I/O throttling object is currently active.
cThread(const char *Description=NULL, bool LowPriority=false)
Creates a new thread.
bool Lock(cThread *Thread)
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting 'running' to false, so that the Action() loop can finish in an or...
static tThreadId mainThreadId
void Release(void)
Releases the global I/O throttling mechanism.
uint64_t Elapsed(void) const