mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-04 07:05:26 -04:00
moved semaphore based thread logic up to RsThread. This should help terminating service threads properly and possibly remove the SIGSEGV when quitting
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@8287 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
c0ecc0da7a
commit
f2d4a237ca
4 changed files with 166 additions and 216 deletions
|
@ -38,9 +38,6 @@ pqithreadstreamer::pqithreadstreamer(PQInterface *parent, RsSerialiser *rss, con
|
||||||
{
|
{
|
||||||
mTimeout = DEFAULT_STREAMER_TIMEOUT;
|
mTimeout = DEFAULT_STREAMER_TIMEOUT;
|
||||||
mSleepPeriod = DEFAULT_STREAMER_SLEEP;
|
mSleepPeriod = DEFAULT_STREAMER_SLEEP;
|
||||||
|
|
||||||
sem_init(&mShouldStopSemaphore,0,0) ;
|
|
||||||
sem_init(&mHasStoppedSemaphore,0,1) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pqithreadstreamer::RecvItem(RsItem *item)
|
bool pqithreadstreamer::RecvItem(RsItem *item)
|
||||||
|
@ -56,88 +53,6 @@ int pqithreadstreamer::tick()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pqithreadstreamer::start()
|
|
||||||
{
|
|
||||||
// mToRun = true;
|
|
||||||
|
|
||||||
#ifdef PQISTREAMER_DEBUG
|
|
||||||
std::cerr << "pqithreadstreamer::run()" << std::endl;
|
|
||||||
std::cerr << " initing should_stop=0" << std::endl;
|
|
||||||
std::cerr << " initing has_stopped=1" << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sem_init(&mShouldStopSemaphore,0,0) ;
|
|
||||||
sem_init(&mHasStoppedSemaphore,0,0) ;
|
|
||||||
|
|
||||||
RsThread::start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pqithreadstreamer::run()
|
|
||||||
{
|
|
||||||
#ifdef PQISTREAMER_DEBUG
|
|
||||||
std::cerr << "pqithreadstream::run()";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// tell the OS to free the thread resources when this function exits
|
|
||||||
// it is a replacement for pthread_join()
|
|
||||||
pthread_detach(pthread_self());
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
int sval =0;
|
|
||||||
sem_getvalue(&mShouldStopSemaphore,&sval) ;
|
|
||||||
|
|
||||||
if(sval > 0)
|
|
||||||
{
|
|
||||||
#ifdef PQISTREAMER_DEBUG
|
|
||||||
std::cerr << "pqithreadstreamer::run(): asked to stop." << std::endl;
|
|
||||||
std::cerr << " setting hasStopped=1" << std::endl;
|
|
||||||
#endif
|
|
||||||
sem_post(&mHasStoppedSemaphore) ;
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
data_tick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pqithreadstreamer::shutdown()
|
|
||||||
{
|
|
||||||
#ifdef PQISTREAMER_DEBUG
|
|
||||||
std::cerr << "pqithreadstreamer::stop()" << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int sval =0;
|
|
||||||
sem_getvalue(&mHasStoppedSemaphore,&sval) ;
|
|
||||||
|
|
||||||
if(sval > 0)
|
|
||||||
{
|
|
||||||
#ifdef PQISTREAMER_DEBUG
|
|
||||||
std::cerr << " thread not running. Quit." << std::endl;
|
|
||||||
#endif
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef PQISTREAMER_DEBUG
|
|
||||||
std::cerr << " calling stop" << std::endl;
|
|
||||||
#endif
|
|
||||||
sem_post(&mShouldStopSemaphore) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pqithreadstreamer::fullstop()
|
|
||||||
{
|
|
||||||
shutdown() ;
|
|
||||||
|
|
||||||
#ifdef PQISTREAMER_DEBUG
|
|
||||||
std::cerr << " waiting stop" << std::endl;
|
|
||||||
#endif
|
|
||||||
sem_wait(&mHasStoppedSemaphore) ;
|
|
||||||
#ifdef PQISTREAMER_DEBUG
|
|
||||||
std::cerr << " finished!" << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int pqithreadstreamer::data_tick()
|
int pqithreadstreamer::data_tick()
|
||||||
{
|
{
|
||||||
uint32_t recv_timeout = 0;
|
uint32_t recv_timeout = 0;
|
||||||
|
|
|
@ -26,19 +26,14 @@
|
||||||
#ifndef MRK_PQI_THREAD_STREAMER_HEADER
|
#ifndef MRK_PQI_THREAD_STREAMER_HEADER
|
||||||
#define MRK_PQI_THREAD_STREAMER_HEADER
|
#define MRK_PQI_THREAD_STREAMER_HEADER
|
||||||
|
|
||||||
#include <semaphore.h>
|
|
||||||
#include "pqi/pqistreamer.h"
|
#include "pqi/pqistreamer.h"
|
||||||
#include "util/rsthreads.h"
|
#include "util/rsthreads.h"
|
||||||
|
|
||||||
class pqithreadstreamer: public pqistreamer, private RsThread
|
class pqithreadstreamer: public pqistreamer, public RsThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
pqithreadstreamer(PQInterface *parent, RsSerialiser *rss, const RsPeerId& peerid, BinInterface *bio_in, int bio_flagsin);
|
pqithreadstreamer(PQInterface *parent, RsSerialiser *rss, const RsPeerId& peerid, BinInterface *bio_in, int bio_flagsin);
|
||||||
|
|
||||||
virtual void start();
|
|
||||||
virtual void shutdown();
|
|
||||||
virtual void fullstop();
|
|
||||||
|
|
||||||
virtual bool RecvItem(RsItem *item);
|
virtual bool RecvItem(RsItem *item);
|
||||||
virtual int tick();
|
virtual int tick();
|
||||||
|
|
||||||
|
@ -55,8 +50,6 @@ protected:
|
||||||
private:
|
private:
|
||||||
/* thread variables */
|
/* thread variables */
|
||||||
RsMutex mThreadMutex;
|
RsMutex mThreadMutex;
|
||||||
sem_t mShouldStopSemaphore;
|
|
||||||
sem_t mHasStoppedSemaphore;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //MRK_PQI_THREAD_STREAMER_HEADER
|
#endif //MRK_PQI_THREAD_STREAMER_HEADER
|
||||||
|
|
|
@ -60,6 +60,41 @@ void *RsThread::rsthread_init(void* p)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RsThread::shutdown()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_THREADS
|
||||||
|
std::cerr << "pqithreadstreamer::stop()" << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int sval =0;
|
||||||
|
sem_getvalue(&mHasStoppedSemaphore,&sval) ;
|
||||||
|
|
||||||
|
if(sval > 0)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_THREADS
|
||||||
|
std::cerr << " thread not running. Quit." << std::endl;
|
||||||
|
#endif
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_THREADS
|
||||||
|
std::cerr << " calling stop" << std::endl;
|
||||||
|
#endif
|
||||||
|
sem_post(&mShouldStopSemaphore) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsThread::fullstop()
|
||||||
|
{
|
||||||
|
shutdown() ;
|
||||||
|
|
||||||
|
#ifdef DEBUG_THREADS
|
||||||
|
std::cerr << " waiting stop" << std::endl;
|
||||||
|
#endif
|
||||||
|
sem_wait(&mHasStoppedSemaphore) ;
|
||||||
|
#ifdef DEBUG_THREADS
|
||||||
|
std::cerr << " finished!" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
void RsThread::start()
|
void RsThread::start()
|
||||||
{
|
{
|
||||||
pthread_t tid;
|
pthread_t tid;
|
||||||
|
@ -67,41 +102,33 @@ void RsThread::start()
|
||||||
|
|
||||||
RS_STACK_MUTEX(mMutex) ;
|
RS_STACK_MUTEX(mMutex) ;
|
||||||
|
|
||||||
#if 0
|
#ifdef DEBUG_THREADS
|
||||||
int ret;
|
std::cerr << "pqithreadstreamer::run()" << std::endl;
|
||||||
ret = pthread_attr_init(&tattr);
|
std::cerr << " initing should_stop=0" << std::endl;
|
||||||
if (doDetached)
|
std::cerr << " initing has_stopped=1" << std::endl;
|
||||||
{
|
|
||||||
ret = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_JOINABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_create(&tid, &tattr, &rsthread_init, data);
|
|
||||||
#endif
|
#endif
|
||||||
|
sem_init(&mShouldStopSemaphore,0,0) ;
|
||||||
|
sem_init(&mHasStoppedSemaphore,0,0) ;
|
||||||
|
|
||||||
int err ;
|
int err ;
|
||||||
|
|
||||||
// pthread_create is a memory barrier
|
// pthread_create is a memory barrier
|
||||||
// -> the new thread will see mIsRunning = true
|
// -> the new thread will see mIsRunning() = true
|
||||||
mIsRunning = true ;
|
|
||||||
if( 0 == (err=pthread_create(&tid, 0, &rsthread_init, data)))
|
if( 0 == (err=pthread_create(&tid, 0, &rsthread_init, data)))
|
||||||
{
|
|
||||||
mTid = tid;
|
mTid = tid;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << "Fatal error: pthread_create could not create a thread. Error returned: " << err << " !!!!!!!" << std::endl;
|
std::cerr << "Fatal error: pthread_create could not create a thread. Error returned: " << err << " !!!!!!!" << std::endl;
|
||||||
mIsRunning = false ;
|
sem_init(&mHasStoppedSemaphore,0,1) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RsThread::RsThread () : mMutex("RsThread")
|
RsThread::RsThread () : mMutex("RsThread")
|
||||||
{
|
{
|
||||||
mIsRunning = false;
|
sem_init(&mShouldStopSemaphore,0,0) ;
|
||||||
|
sem_init(&mHasStoppedSemaphore,0,1) ;
|
||||||
|
|
||||||
#ifdef WINDOWS_SYS
|
#ifdef WINDOWS_SYS
|
||||||
memset (&mTid, 0, sizeof(mTid));
|
memset (&mTid, 0, sizeof(mTid));
|
||||||
|
@ -110,24 +137,43 @@ RsThread::RsThread () : mMutex("RsThread")
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsThread::join() /* waits for the the mTid thread to stop */
|
|
||||||
{
|
|
||||||
// do we need a mutex for this ?
|
|
||||||
mIsRunning = false;
|
|
||||||
|
|
||||||
void *ptr;
|
|
||||||
pthread_join(mTid, &ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RsThread::stop()
|
|
||||||
{
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RsThread::isRunning()
|
bool RsThread::isRunning()
|
||||||
{
|
{
|
||||||
// do we need a mutex for this ?
|
// do we need a mutex for this ?
|
||||||
return mIsRunning;
|
int sval =0;
|
||||||
|
sem_getvalue(&mHasStoppedSemaphore,&sval) ;
|
||||||
|
|
||||||
|
return !sval ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsThread::run()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_THREADS
|
||||||
|
std::cerr << "pqithreadstream::run()";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// tell the OS to free the thread resources when this function exits
|
||||||
|
// it is a replacement for pthread_join()
|
||||||
|
pthread_detach(pthread_self());
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
int sval =0;
|
||||||
|
sem_getvalue(&mShouldStopSemaphore,&sval) ;
|
||||||
|
|
||||||
|
if(sval > 0)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_THREADS
|
||||||
|
std::cerr << "pqithreadstreamer::run(): asked to stop." << std::endl;
|
||||||
|
std::cerr << " setting hasStopped=1" << std::endl;
|
||||||
|
#endif
|
||||||
|
sem_post(&mHasStoppedSemaphore) ;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_tick();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RsQueueThread::RsQueueThread(uint32_t min, uint32_t max, double relaxFactor )
|
RsQueueThread::RsQueueThread(uint32_t min, uint32_t max, double relaxFactor )
|
||||||
|
@ -137,9 +183,7 @@ RsQueueThread::RsQueueThread(uint32_t min, uint32_t max, double relaxFactor )
|
||||||
mLastWork = time(NULL) ;
|
mLastWork = time(NULL) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsQueueThread::run()
|
void RsQueueThread::data_tick()
|
||||||
{
|
|
||||||
while(isRunning())
|
|
||||||
{
|
{
|
||||||
bool doneWork = false;
|
bool doneWork = false;
|
||||||
while(workQueued() && doWork())
|
while(workQueued() && doWork())
|
||||||
|
@ -177,7 +221,6 @@ void RsQueueThread::run()
|
||||||
}
|
}
|
||||||
usleep(mLastSleep * 1000); // mLastSleep msec
|
usleep(mLastSleep * 1000); // mLastSleep msec
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void RsMutex::unlock()
|
void RsMutex::unlock()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
#ifndef RSIFACE_THREADS_H
|
|
||||||
#define RSIFACE_THREADS_H
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "$Id: rsthreads.h,v 1.1 2007-02-19 20:08:30 rmf24 Exp $"
|
* "$Id: rsthreads.h,v 1.1 2007-02-19 20:08:30 rmf24 Exp $"
|
||||||
*
|
*
|
||||||
|
@ -26,11 +23,13 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <semaphore.h>
|
||||||
|
|
||||||
/* RsIface Thread Wrappers */
|
/* RsIface Thread Wrappers */
|
||||||
|
|
||||||
|
@ -183,20 +182,22 @@ public:
|
||||||
virtual ~RsThread() {}
|
virtual ~RsThread() {}
|
||||||
|
|
||||||
void start() ;
|
void start() ;
|
||||||
void join(); /* waits for the the mTid thread to stop */
|
void shutdown();
|
||||||
void stop(); /* calls pthread_exit() */
|
void fullstop();
|
||||||
|
void join() { fullstop() ; } // used for compatibility
|
||||||
bool isRunning();
|
bool isRunning();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void run() = 0; /* called once the thread is started. Should be overloaded by subclasses. */
|
void run() ; /* called once the thread is started. Should be overloaded by subclasses. */
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void *rsthread_init(void*) ;
|
static void *rsthread_init(void*) ;
|
||||||
|
|
||||||
pthread_t mTid;
|
pthread_t mTid;
|
||||||
RsMutex mMutex;
|
RsMutex mMutex;
|
||||||
|
|
||||||
bool mIsRunning;
|
sem_t mShouldStopSemaphore;
|
||||||
|
sem_t mHasStoppedSemaphore;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,12 +208,11 @@ class RsQueueThread: public RsThread
|
||||||
RsQueueThread(uint32_t min, uint32_t max, double relaxFactor );
|
RsQueueThread(uint32_t min, uint32_t max, double relaxFactor );
|
||||||
virtual ~RsQueueThread() { return; }
|
virtual ~RsQueueThread() { return; }
|
||||||
|
|
||||||
virtual void run();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual bool workQueued() = 0;
|
virtual bool workQueued() = 0;
|
||||||
virtual bool doWork() = 0;
|
virtual bool doWork() = 0;
|
||||||
|
virtual void data_tick() ;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t mMinSleep; /* ms */
|
uint32_t mMinSleep; /* ms */
|
||||||
|
@ -222,4 +222,3 @@ virtual bool doWork() = 0;
|
||||||
float mRelaxFactor;
|
float mRelaxFactor;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue