~drizzle-trunk/drizzle/development

1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
2
 *
3
 * PrimeBase Media Stream for MySQL
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
18
 *
19
 * Original author: Paul McCullagh (H&G2JCtL)
20
 * Continued development: Barry Leslie
21
 *
22
 * 2007-05-20
23
 *
24
 * CORE SYSTEM:
25
 * A independently running thread.
26
 *
27
 */
28
29
#include "CSConfig.h"
30
31
#ifdef OS_WINDOWS
32
#include <signal.h>
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
33
//#include "uniwin.h"
34
#define SIGUSR1 30
35
#define SIGUSR2 31
36
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
37
#else
38
#include <signal.h>
39
#include <sys/signal.h>
40
#include <unistd.h>
1841.1.6 by Barry.Leslie at PrimeBase
Updating PBMS code to match pbms revision 244
41
#endif
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
42
#include <errno.h>
43
44
#include "CSGlobal.h"
45
#include "CSLog.h"
46
#include "CSException.h"
47
#include "CSThread.h"
48
#include "CSStrUtil.h"
49
#include "CSMemory.h"
50
51
/*
52
 * ---------------------------------------------------------------
53
 * SIGNAL HANDLERS
54
 */
55
56
extern "C" {
57
58
59
static void td_catch_signal(int sig)
60
{
61
	CSThread *self;
62
63
	if ((self = CSThread::getSelf())) {
64
		if (self->isMain()) {
65
			/* The main thread will pass on a signal to all threads: */
66
			if (self->myThreadList)
67
				self->myThreadList->signalAllThreads(sig);
68
			self->setSignalPending(sig);
69
		}
70
	}
71
	
72
}
73
74
static  void td_throw_signal(int sig)
75
{
76
	CSThread *self;
77
78
	if ((self = CSThread::getSelf())) {
79
		if (self->isMain()) {
80
			/* The main thread will pass on a signal to all threads: */
81
			if (self->myThreadList)
82
				self->myThreadList->signalAllThreads(sig);
83
		}
84
		self->setSignalPending(sig);
85
		self->interrupted();
86
	}
87
}
88
89
static bool td_setup_signals(CSThread *thread)
90
{
91
#ifdef OS_WINDOWS
92
	return true;
93
#else
94
	struct sigaction action;
95
96
    sigemptyset(&action.sa_mask);
97
    action.sa_flags = 0;
98
99
    action.sa_handler = td_catch_signal;
100
101
	if (sigaction(SIGUSR2, &action, NULL) == -1)
102
		goto error_occurred;
103
104
    action.sa_handler = td_throw_signal;
105
106
	return true;
107
108
	error_occurred:
109
110
	if (thread) {
111
		thread->myException.initOSError(CS_CONTEXT, errno);
112
		thread->myException.setStackTrace(thread);
113
	}
114
	else
115
		CSException::throwOSError(CS_CONTEXT, errno);
116
	return false;
117
#endif
118
}
119
120
}
121
122
/*
123
 * ---------------------------------------------------------------
124
 * THREAD LISTS
125
 */
126
127
void CSThreadList::signalAllThreads(int sig)
128
{
129
	CSThread *ptr;
130
131
	enter_();
1548.2.19 by Barry.Leslie at PrimeBase
Fixes for longjmp clobber problem, (Hopefully)
132
	lock_(this);
133
	ptr = (CSThread *) getBack();
134
	while (ptr) {
135
		if (ptr != self)
136
			ptr->signal(sig);
137
		ptr = (CSThread *) ptr->getNextLink();
138
	}
139
	unlock_(this);
140
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
141
	exit_();
142
}
143
144
void CSThreadList::quitAllThreads()
145
{
146
	CSThread *ptr;
147
148
	enter_();
1548.2.19 by Barry.Leslie at PrimeBase
Fixes for longjmp clobber problem, (Hopefully)
149
	lock_(this);
150
	
151
	ptr = (CSThread *) getBack();
152
	while (ptr) {
153
		if (ptr != self)
154
			ptr->myMustQuit = true;
155
		ptr = (CSThread *) ptr->getNextLink();
156
	}
157
	
158
	unlock_(this);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
159
	exit_();
160
}
161
162
void CSThreadList::stopAllThreads()
163
{
164
	CSThread *thread;
165
166
	enter_();
167
	for (;;) {
168
		/* Get a thread that is not self! */
1548.2.19 by Barry.Leslie at PrimeBase
Fixes for longjmp clobber problem, (Hopefully)
169
		lock_(this);
170
		if ((thread = (CSThread *) getBack())) {
171
			while (thread) {
172
				if (thread != self)
173
					break;
174
				thread = (CSThread *) thread->getNextLink();
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
175
			}
1548.2.19 by Barry.Leslie at PrimeBase
Fixes for longjmp clobber problem, (Hopefully)
176
		}
177
		if (thread)
178
			thread->retain();
179
		unlock_(this);
180
		
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
181
		if (!thread)
182
			break;
1548.2.19 by Barry.Leslie at PrimeBase
Fixes for longjmp clobber problem, (Hopefully)
183
			
184
		push_(thread);
185
		thread->stop();
186
		release_(thread);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
187
	}
188
	exit_();
189
}
190
191
/*
192
 * ---------------------------------------------------------------
193
 * CSTHREAD
194
 */
195
196
void CSThread::addToList()
197
{
198
	if (myThreadList) {
199
		enter_();
200
		ASSERT(self == this);
201
		lock_(myThreadList);
202
		myThreadList->addFront(self);
203
		isRunning = true;
204
		unlock_(myThreadList);
205
		exit_();
206
	}
207
	else
208
		isRunning = true;
209
}
210
	
211
void CSThread::removeFromList()
212
{
213
	if (myThreadList && isRunning) {
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
214
		CSThread *myself = this; // pop_() wants to take a reference to its parameter.
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
215
		enter_();
216
		/* Retain the thread in order to ensure
217
		 * that after it is removed from the list,
218
		 * that it is not freed! This would make the
219
		 * unlock_() call invalid, because it requires
220
		 * on the thread.
221
		 */
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
222
		push_(myself);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
223
		lock_(myThreadList);
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
224
		myThreadList->remove(RETAIN(myself));
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
225
		unlock_(myThreadList);
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
226
		pop_(myself);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
227
		outer_();
228
	}
229
	this->release();
230
}
231
1548.2.38 by Barry.Leslie at PrimeBase
Fixed some solaris build problems.
232
void *CSThread::dispatch(void *arg)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
233
{
234
	CSThread		*self;
235
	void			*return_data = NULL;
236
	int				err;
237
238
	/* Get a reference to myself: */
239
	self = reinterpret_cast<CSThread*>(arg);
240
	ASSERT(self);
241
242
	/* Store my thread in the thread key: */
243
	if ((err = pthread_setspecific(CSThread::sThreadKey, self))) {
244
		CSException::logOSError(self, CS_CONTEXT, err);
245
		return NULL;
246
	}
247
248
	/*
249
	 * Make sure the thread is not freed while we
250
	 * are running:
251
	 */
252
	self->retain();
253
254
	try_(a) {
255
		td_setup_signals(NULL);
256
257
		/* Add the thread to the list: */
258
		self->addToList();
259
260
		// Run the task from the correct context
261
		return_data = self->run();
262
	}
263
	catch_(a) {
264
		self->logException();
265
	}
266
	cont_(a);
267
268
	/*
269
	 * Removing from the thread list will also release the thread.
270
	 */
271
	self->removeFromList();
272
273
	// Exit the thread
274
	return return_data;
275
}
276
1548.2.38 by Barry.Leslie at PrimeBase
Fixed some solaris build problems.
277
1643.1.8 by Monty Taylor
Fixed a couple of solaris build issues. Callback functions passed to
278
extern "C"
1643.1.10 by Monty Taylor
Fixed OSX build errors.
279
{
280
1548.2.38 by Barry.Leslie at PrimeBase
Fixed some solaris build problems.
281
static void *dispatch_wrapper(void *arg)
282
{
283
	return CSThread::dispatch(arg);
284
}
285
1643.1.10 by Monty Taylor
Fixed OSX build errors.
286
}
287
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
288
void *CSThread::run()
289
{
290
	if (iRunFunc)
291
		return iRunFunc();
292
	return NULL;
293
}
294
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
295
void CSThread::start(bool detached)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
296
{
297
	int err;
298
1548.2.38 by Barry.Leslie at PrimeBase
Fixed some solaris build problems.
299
	err = pthread_create(&iThread, NULL, dispatch_wrapper, (void *) this);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
300
	if (err)
301
		CSException::throwOSError(CS_CONTEXT, err);
302
	while (!isRunning) {
303
		/* Check if the thread is still alive,
304
		 * so we don't hang forever.
305
		 */
306
		if (pthread_kill(iThread, 0))
307
			break;
308
		usleep(10);
309
	}
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
310
	
311
	isDetached = detached;
312
	if (detached)
313
		pthread_detach(iThread);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
314
}
315
316
void CSThread::stop()
317
{
318
	signal(SIGTERM);
319
	join();
320
}
321
322
void *CSThread::join()
323
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
324
	void	*return_data = NULL;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
325
	int		err;
326
327
	enter_();
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
328
	if (isDetached) {
329
		while (isRunning && !pthread_kill(iThread, 0)) 
330
			usleep(100);
331
	} else if ((err = pthread_join(iThread, &return_data))) {
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
332
		CSException::throwOSError(CS_CONTEXT, err);
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
333
	}
334
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
335
	return_(return_data);
336
}
337
338
void CSThread::setSignalPending(unsigned int sig)
339
{
340
	if (sig == SIGTERM)
341
		/* The terminate signal takes priority: */
342
		signalPending = SIGTERM;
343
	else if (!signalPending)
344
		/* Otherwise, first signal wins... */
345
		signalPending = sig;
346
}
347
348
void CSThread::signal(unsigned int sig)
349
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
350
#ifndef OS_WINDOWS // Currently you cannot signal threads on windows.
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
351
	int err;
352
353
	setSignalPending(sig);
354
	if ((err = pthread_kill(iThread, SIGUSR2)))
355
	{
356
		/* Ignore the error if the process does not exist! */
357
		if (err != ESRCH) /* No such process */
358
			CSException::throwOSError(CS_CONTEXT, err);
359
	}
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
360
#endif
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
361
}
362
363
void CSThread::throwSignal()
364
{
365
	int sig;
366
367
	if ((sig = signalPending) && !ignoreSignals) {
368
		signalPending = 0;
369
		CSException::throwSignal(CS_CONTEXT, sig);
370
	}
371
}
372
373
bool CSThread::isMain()
374
{
375
	return iIsMain;
376
}
377
378
/*
379
 * -----------------------------------------------------------------------
380
 * THROWING EXCEPTIONS
381
 */
382
383
/* 
384
 * When an exception is .
385
 */
386
387
void CSThread::releaseObjects(CSReleasePtr top)
388
{
389
	CSObject *obj;
390
391
	while (relTop > top) {
392
		/* Remove and release or unlock the object on the top of the stack: */
393
		relTop--;
394
		switch(relTop->r_type) {
395
			case CS_RELEASE_OBJECT:
396
				if ((obj = relTop->x.r_object))
397
					obj->release();
398
				break;
399
			case CS_RELEASE_MUTEX:
400
				if (relTop->x.r_mutex)
401
					relTop->x.r_mutex->unlock();
402
				break;
403
			case CS_RELEASE_POOLED:
404
				if (relTop->x.r_pooled)
405
					relTop->x.r_pooled->returnToPool();
406
				break;
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
407
			case CS_RELEASE_MEM:
408
				if (relTop->x.r_mem)
409
					cs_free(relTop->x.r_mem);
410
				break;
411
			case CS_RELEASE_OBJECT_PTR:
412
				if ((relTop->x.r_objectPtr) && (obj = *(relTop->x.r_objectPtr)))
413
					obj->release();
414
				break;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
415
		}
416
	}
417
}
418
419
/* Throw an already registered error: */
420
void CSThread::throwException()
421
{
422
	/* Record the stack trace: */
423
	if (this->jumpDepth > 0 && this->jumpDepth <= CS_JUMP_STACK_SIZE) {
424
		/*
425
		 * As recommended by Barry:
426
		 * release the objects before we jump!
427
		 * This has the advantage that the stack context is still
428
		 * valid when the resources are released.
429
		 */
430
		releaseObjects(this->jumpEnv[this->jumpDepth-1].jb_res_top);
431
432
		/* Then do the longjmp: */
433
		longjmp(this->jumpEnv[this->jumpDepth-1].jb_buffer, 1);
434
	}
435
}
436
437
void CSThread::logStack(int depth, const char *msg)
438
{
439
	char buffer[CS_EXC_CONTEXT_SIZE +1];
440
	CSL.lock();
441
	CSL.log(this, CSLog::Trace, msg);
442
	
443
	for (int i= callTop-1; i>=0 && depth; i--, depth--) {
444
		cs_format_context(CS_EXC_CONTEXT_SIZE, buffer,
445
			callStack[i].cs_func, callStack[i].cs_file, callStack[i].cs_line);
446
		strcat(buffer, "\n");
447
		CSL.log(this, CSLog::Trace, buffer);
448
	}
449
	CSL.unlock();
450
}
451
452
void CSThread::logException()
453
{
454
	myException.log(this);
455
}
456
457
/*
458
 * This function is called when an exception is caught.
459
 * It restores the function call top and frees
460
 * any resource allocated by lower levels.
461
 */
462
void CSThread::caught()
463
{
464
	/* Restore the call top: */
465
	this->callTop = this->jumpEnv[this->jumpDepth].jb_call_top;
466
467
	/* 
468
	 * Release all all objects that were pushed after
469
	 * this jump position was set:
470
	 */
471
	releaseObjects(this->jumpEnv[this->jumpDepth].jb_res_top);
472
}
473
474
/*
475
 * ---------------------------------------------------------------
476
 * STATIC METHODS
477
 */
478
479
pthread_key_t	CSThread::sThreadKey;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
480
bool			CSThread::isUp = false;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
481
482
bool CSThread::startUp()
483
{
484
	int err;
485
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
486
	isUp = false;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
487
	if ((err = pthread_key_create(&sThreadKey, NULL))) {
488
		CSException::logOSError(CS_CONTEXT, errno);
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
489
	} else
490
		isUp = true;
491
		
492
	return isUp;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
493
}
494
495
void CSThread::shutDown()
496
{
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
497
	isUp = false;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
498
}
499
500
bool CSThread::attach(CSThread *thread)
501
{
502
	ASSERT(!getSelf());
503
	
504
	if (!thread) {
505
		CSException::logOSError(CS_CONTEXT, ENOMEM);
506
		return false;
507
	}
508
509
	if (!setSelf(thread))
510
		return false;
511
512
	/* Now we are ready to receive signals: */
513
	if (!td_setup_signals(thread))
514
		return false;
515
516
	thread->addToList();
517
	thread->retain();
518
	return true;
519
}
520
521
void CSThread::detach(CSThread *thread)
522
{
523
	ASSERT(!getSelf() || getSelf() == thread);
524
	thread->removeFromList();
525
	thread->release();
526
	pthread_setspecific(sThreadKey, NULL);
527
}
528
529
CSThread* CSThread::getSelf()
530
{
1548.2.20 by Barry.Leslie at PrimeBase
Code cleanup.
531
	CSThread* self = NULL;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
532
	
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
533
	if ((!isUp) || !(self = (CSThread*) pthread_getspecific(sThreadKey)))
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
534
		return (CSThread*) NULL;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
535
		
536
#ifdef DEBUG
1841.1.6 by Barry.Leslie at PrimeBase
Updating PBMS code to match pbms revision 244
537
	/* PMC - Problem is, if this is called when releasing a
538
	 * thread, then we have the reference count equal to
539
	 * zero.
540
	if (self && !self->iRefCount) {
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
541
		pthread_setspecific(sThreadKey, NULL);
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
542
		CSException::throwAssertion(CS_CONTEXT, "Freed self pointer referenced.");
1841.1.6 by Barry.Leslie at PrimeBase
Updating PBMS code to match pbms revision 244
543
	}
544
	*/
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
545
#endif
546
547
	return self;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
548
}
549
550
bool CSThread::setSelf(CSThread *self)
551
{
552
	int err;
553
554
	if (self) {
555
		self->iThread = pthread_self();
556
557
		/* Store my thread in the thread key: */
558
		if ((err = pthread_setspecific(sThreadKey, self))) {
559
			self->myException.initOSError(CS_CONTEXT, err);
560
			self->myException.setStackTrace(self);
561
			return false;
562
		}
563
	}
564
	else
565
		pthread_setspecific(sThreadKey, NULL);
566
	return true;
567
}
568
569
/* timeout is in milliseconds */
570
void CSThread::sleep(unsigned long timeout)
571
{
572
	enter_();
573
	usleep(timeout * 1000);
574
	self->interrupted();
575
	exit_();
576
}
577
1548.2.23 by Barry.Leslie at PrimeBase
And more cleanup.
578
#ifdef DEBUG
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
579
int cs_assert(const char *func, const char *file, int line, const char *message)
580
{
581
	CSException::throwAssertion(func, file, line, message);
582
	return 0;
583
}
584
585
int cs_hope(const char *func, const char *file, int line, const char *message)
586
{
587
	CSException e;
588
		
589
	e.initAssertion(func, file, line, message);
590
	e.log(NULL);
591
	return 0;
592
}
1548.2.23 by Barry.Leslie at PrimeBase
And more cleanup.
593
#endif
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
594
595
CSThread *CSThread::newThread(CSString *name, ThreadRunFunc run_func, CSThreadList *list)
596
{
597
	CSThread *thd;
598
599
	enter_();
600
	if (!(thd = new CSThread(list))) {
601
		name->release();
602
		CSException::throwOSError(CS_CONTEXT, ENOMEM);
603
	}
604
	thd->threadName = name;
605
	thd->iRunFunc = run_func;
606
	return_(thd);
607
}
608
609
CSThread *CSThread::newCSThread()
610
{
611
	CSThread *thd = NULL;
612
613
	if (!(thd = new CSThread(NULL))) {
614
		CSException::throwOSError(CS_CONTEXT, ENOMEM);
615
	}
616
	
617
	return thd;
618
}
619
620
/*
621
 * ---------------------------------------------------------------
622
 * DAEMON THREADS
623
 */
624
625
CSDaemon::CSDaemon(time_t wait_time, CSThreadList *list):
626
CSThread(list),
627
CSSync(),
628
myWaitTime(wait_time),
629
iSuspended(false),
630
iSuspendCount(0)
631
{
632
}
633
634
CSDaemon::CSDaemon(CSThreadList *list):
635
CSThread(list),
636
CSSync(),
637
myWaitTime(0),
638
iSuspended(false),
639
iSuspendCount(0)
640
{
641
}
642
1841.1.5 by barry-leslie
Fixed some compiler complaints with PBMS build.
643
void CSDaemon::try_Run(CSThread *self, const bool c_must_sleep)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
644
{
645
	try_(a) {
1841.1.5 by barry-leslie
Fixed some compiler complaints with PBMS build.
646
		 bool must_sleep = c_must_sleep; // This done to avoid longjmp() clobber.
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
647
		while (!myMustQuit) {
648
			if (must_sleep) {
649
				lock_(this);
650
				if (myWaitTime)
651
					suspendedWait(myWaitTime);
652
				else
653
					suspendedWait();
654
				unlock_(this);
655
				if (myMustQuit)
656
					break;
657
			}
658
			must_sleep = doWork();
659
		}
660
	}
661
	catch_(a) {
662
		if (!handleException())
663
			myMustQuit = true;
664
	}
665
	cont_(a);
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
666
}
667
668
void *CSDaemon::run()
669
{
670
	bool must_sleep = false;
671
672
	enter_();
673
674
	myMustQuit = !initializeWork();
675
676
	while  (!myMustQuit) {
677
		try_Run(self, must_sleep);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
678
		must_sleep = true;
679
	}
680
1548.2.11 by Barry.Leslie at PrimeBase
Removed libxml reqirement by using a home grown xml parser.
681
	/* Prevent signals from going off in completeWork! */
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
682
	ignoreSignals = true;
683
1548.2.11 by Barry.Leslie at PrimeBase
Removed libxml reqirement by using a home grown xml parser.
684
	return_(completeWork());
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
685
}
686
687
bool CSDaemon::doWork()
688
{
689
	if (iRunFunc)
690
		(void) iRunFunc();
691
	return true;
692
}
693
694
bool CSDaemon::handleException()
695
{
696
	if (!myMustQuit)
697
		logException();
698
	return true;
699
}
700
701
void CSDaemon::wakeup()
702
{
703
	CSSync::wakeup();
704
}
705
706
void CSDaemon::stop()
707
{
708
	myMustQuit = true;
709
	wakeup();
710
	signal(SIGTERM);
711
	join();
712
}
713
714
void CSDaemon::suspend()
715
{
716
	enter_();
717
	lock_(this);
718
	iSuspendCount++;
719
	while (!iSuspended && !myMustQuit)
720
		wait(500);
721
	if (!iSuspended)
722
		iSuspendCount--;
723
	unlock_(this);
724
	exit_();
725
}
726
727
void CSDaemon::resume()
728
{
729
	enter_();
730
	lock_(this);
731
	if (iSuspendCount > 0)
732
		iSuspendCount--;
733
	wakeup();
734
	unlock_(this);
735
	exit_();
736
}
737
738
void CSDaemon::suspended()
739
{
740
	if (!iSuspendCount || myMustQuit) {
741
		iSuspended = false;
742
		return;
743
	}
744
	enter_();
745
	lock_(this);
746
	while (iSuspendCount && !myMustQuit) {
747
		iSuspended = true;
748
		wait(500);
749
	}
750
	iSuspended = false;
751
	unlock_(this);
752
	exit_();
753
}
754
755
void CSDaemon::suspendedWait()
756
{
757
	iSuspended = true;
758
	wait();
759
	if (iSuspendCount)
760
		suspended();
761
}
762
763
void CSDaemon::suspendedWait(time_t milli_sec)
764
{
765
	iSuspended = true;
766
	wait(milli_sec);
767
	if (iSuspendCount)
768
		suspended();
769
	else
770
		iSuspended = false;
771
}
772
773
/*
774
 * ---------------------------------------------------------------
775
 * THREAD POOLS
776
 */
777
778