A two-thread problem that the program never exit as I expect - c++

I designed a simple logging component, but I encountered some problems. The Logging object will create a thread to save logs from buffer in the background. The main thread writes logs into buffer. However, because I use pthread_detach, the main thread will exit even if the Logging thread is still working.
I use pthread_cond_t to solve that problem. I set the LastWriteTime, which represents the last time when main thread wrote to the log. If there has been no log for a period of time, the Logging thread will notify the main thread.
But the program blocks and never exits.
#include <string>
#include <cstring>
#include <string.h>
#include <iostream>
#include <pthread.h>
#include <sys/time.h>
using namespace std;
int64_t get_current_millis(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
void *run(void *args);
class Logging
{
public:
static Logging *LoggingPtr;
pthread_mutex_t ExitMutex;
pthread_cond_t ExitCond;
struct timeval LastWriteTime;
Logging() : ExitMutex(PTHREAD_MUTEX_INITIALIZER), ExitCond(PTHREAD_COND_INITIALIZER)
{
pthread_t pid;
pthread_create(&pid, NULL, run, NULL);
pthread_detach(pid);
}
bool CheckExpired(struct timeval lastWriteTime, size_t wait_time)
{
struct timeval now;
gettimeofday(&now, NULL);
long now_sec = now.tv_sec * 1000 + now.tv_usec / 1000;
long last_sec = lastWriteTime.tv_sec * 1000 + lastWriteTime.tv_usec / 1000;
// expired time: wait_time(ms)
return now_sec - last_sec > wait_time ? true : false;
}
void Save()
{
cout << "in the save" << endl;
while (true)
{
if (CheckExpired(LastWriteTime, 3000))
{
pthread_cond_signal(&ExitCond);
}
}
}
static Logging *Init()
{
while (!LoggingPtr)
{
LoggingPtr = new Logging();
}
return LoggingPtr;
}
void Append()
{
for (size_t i = 0; i < 100000; i++)
{
pthread_mutex_lock(&ExitMutex);
gettimeofday(&LastWriteTime, NULL);
pthread_mutex_unlock(&ExitMutex);
}
}
void Exit()
{
while (true)
{
if (CheckExpired(LastWriteTime, 3000))
{
pthread_cond_signal(&ExitCond);
}
}
pthread_mutex_lock(&ExitMutex);
// 3000 means that the wait_time is 3s
while (!CheckExpired(this->LastWriteTime, 3000))
{
pthread_cond_wait(&ExitCond, &ExitMutex);
}
pthread_mutex_unlock(&ExitMutex);
}
};
void *run(void *args)
{
Logging::Init()->Save();
return NULL;
}
Logging *Logging::LoggingPtr = nullptr;
int main()
{
uint64_t start_ts = get_current_millis();
Logging LOG;
LOG.Append();
LOG.Exit();
uint64_t end_ts = get_current_millis();
std::cout << "wait " << (end_ts - start_ts) / 1000 << "s" << std::endl;
return 0;
}

Related

Trying to call a certain function each time

Okay, so I've an assignment with threads.I'm suppose to change the current running threads each period of time, let's say a second. First of all I've created a Thread class:
typedef unsigned long address_t;
#define JB_SP 6
#define JB_PC 7
#define STACK_SIZE (4096)
using namespace std;
class Thread{
public:
enum State{
BLOCKED,
READY,
RUNNING
};
Thread(int tid, void(*f)(void), int stack_size) :
tid(tid), stack_size(stack_size){
address_t sp, pc;
sp = (address_t)stack + STACK_SIZE - sizeof(address_t);
pc = (address_t)f;
sigsetjmp(env, 1);
(env->__jmpbuf)[JB_SP] = translate_address(sp);
(env->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&env->__saved_mask);
state = READY;
quantums = 0;
}
Thread (){}
address_t translate_address(address_t addr)
{
address_t ret;
asm volatile("xor %%fs:0x30,%0\n"
"rol $0x11,%0\n"
: "=g" (ret)
: "0" (addr));
return ret;
}
State get_state() const
{
return state;
}
void set_state(State state1)
{
state = state1;
}
int get_id() const
{
return tid;
}
pthread_t& get_thread()
{
return thread;
}
sigjmp_buf& get_env()
{
return env;
}
void raise_quantums()
{
quantums ++;
}
int get_quantums()
{
return quantums;
}
int add_to_sync(int tid)
{
sync.push_back(tid);
}
bool appear_in_sync_list(int tid)
{
return (find(sync.begin(), sync.end(), tid) != sync.end());
}
private:
vector<int> sync;
int quantums;
State state;
char stack[STACK_SIZE];
sigjmp_buf env;
pthread_t thread;
int tid;
int stack_size;
};
I've this function which changes threads:
void running_thread(int sigNum)
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigprocmask(SIG_SETMASK, &set, NULL);
total_quantum ++;
if (currentThread.get_state() == Thread::RUNNING)
{
Thread& t = ready_threads.back();
ready_threads.pop_back();
currentThread.set_state(Thread::READY);
ready_threads.push_back(currentThread);
sigsetjmp(currentThread.get_env(), 1);
currentThread = t;
t.raise_quantums();
siglongjmp(currentThread.get_env(), 1);
}
if (currentThread.get_state() == Thread::BLOCKED)
{
Thread &t = ready_threads.back();
ready_threads.pop_back();
currentThread.set_state(Thread::BLOCKED);
blocked_threads.push_back(currentThread);
sigsetjmp(currentThread.get_env(), 1);
currentThread = t;
t.raise_quantums();
siglongjmp(currentThread.get_env(), 1);
}
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigprocmask(SIG_UNBLOCK, &set, NULL);
}
It actually doesn't matter what it do, my problem is that it isn't even called.
My program first call this function:
int clock_set()
{
int seconds = quantum / SECOND;
int usecs = quantum - seconds*SECOND;
timer.it_value.tv_sec = seconds;
timer.it_value.tv_usec = usecs;
timer.it_interval.tv_sec = seconds;
timer.it_interval.tv_usec = usecs;
struct sigaction sa;
sa.sa_handler = &running_thread;
if (sigaction(SIGVTALRM, &sa,NULL) < 0) {
cerr << "system error: sigaction error.";
return FAILURE;
}
// Start a virtual timer. It counts down whenever this process is executing.
if (setitimer (ITIMER_VIRTUAL, &timer, NULL)) {
cerr << "system error: setitimer error.";
return FAILURE;
}
return SUCCESS;
}
Basically I was trying to make running_thread get activate each second, so I Was using sigaction and sa_handler.
This is my main function:
int main()
{
uthread_init(1000000) // Initiliaze variable 'quantum' to be a second, this function also calls clock_set
uthread_spawn(&g); // Creating a thread object with function g inserting it to ready_threads vector and to threads vector
uthread_spawn(&f); // creating a thread object with function f inserting it to ready_threads vector and to threads vector
}
The vector "ready_threads" has 2 threads in it.
Why doesn't it call running_thread?

Assertion failed on __pthread_mutex_cond_lock_full in a load test

I used the following code to create a timer object in my c++ application running on a debian 8.
class Timer
{
private:
std::condition_variable cond_;
std::mutex mutex_;
int duration;
void *params;
public:
Timer::Timer(void (*func)(void*))
{
this->handler = func;
this->duration = 0;
this->params = NULL;
};
Timer::~Timer(){};
void Timer::start(int duree, void* handlerParams)
{
this->duration = duree;
this->params = handlerParams;
/*
* Launch the timer thread and wait it
*/
std::thread([this]{
std::unique_lock<std::mutex> mlock(mutex_);
std::cv_status ret = cond_.wait_for(mlock,
std::chrono::seconds(duration));
if ( ret == std::cv_status::timeout )
{
handler(params);
}
}).detach();
};
void Timer::stop()
{
cond_.notify_all();
}
};
It works correctly under gdb and under normal conditions, but in a load test of 30 requests or more, it crashes with the assertion :
nptl/pthread_mutex_lock.c:350: __pthread_mutex_cond_lock_full: Assertion `(-(e)) != 3 || !robust' failed.
I don't understand the cause of this assertion. Can anyone help me please ??
Thank you
Basically you have a detached thread that accesses the timer object, so it's likely that you destroyed the Timer object but the thread is still running and accessing it's member(mutex, conditional variable).
The assert itself says, from glibc source code, that the owner of the mutex has died.
Thanks a lot for your comments ! I'll try to change the thread detach, and do the load tests.
This is a MVCE of my problem, which is a part of a huge application.
/**
* \file Timer.hxx
* \brief Definition of Timer class.
*/
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>
class Timer
{
private:
std::condition_variable cond_;
std::mutex mutex_;
int duration;
void *params;
public:
Timer(void (*func)(void*));
~Timer();
void (*handler)(void*);
void start(int duree, void* handlerParams);
void stop();
};
/*
* Timer.cxx
*/
#include "Timer.hxx"
Timer::Timer(void (*func)(void*))
{
//this->set_handler(func, params);
this->handler = func;
this->duration = 0;
this->params = NULL;
}
Timer::~Timer()
{
}
void Timer::start(int duree, void* handlerParams)
{
this->duration = duree;
this->params = handlerParams;
/*
* Launch the timer thread and wait it
*/
std::thread([this]{
std::unique_lock<std::mutex> mlock(mutex_);
std::cv_status ret = cond_.wait_for(mlock, std::chrono::seconds(duration));
if ( ret == std::cv_status::timeout )
{
handler(params);
}
}).detach();
}
void Timer::stop()
{
cond_.notify_all();
}
/*
* MAIN
*/
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include "Timer.hxx"
using namespace std;
void timeoutHandler(void* params)
{
char* data= (char*)params;
cout << "Timeout triggered !! Received data is: " ;
if (data!=NULL)
cout << data << endl;
}
int main(int argc, char **argv)
{
int delay=5;
char data[20] ="This is a test" ;
Timer *t= new Timer(&timeoutHandler) ;
t->start(delay, data);
cout << "Timer started !! " << endl;
sleep(1000);
t->stop();
delete t;
cout << "Timer deleted !! " << endl;
return 0;
}

sem_timedwait with CLOCK_MONOTONIC_RAW/CLOCK_MONOTONIC

The example code for int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); uses CLOCK_REALTIME as the time source from clock_gettime(struct timespec *timeout) but this is susceptible to system clock time changes for example some other process changing time backwards.
Is there a support for sem_timedwait to support CLOCK_MONOTONIC time source
below is some example code for reference.
struct timespec ts;
sem_t sema;
sem_init(&sema, 0, 0)
int ret;
if ( -1 != (ret = clock_gettime(CLOCK_REALTIME, &ts))){
ts.tv_sec += 1;
return sem_timedwait(sema, &ts);
}
Is there a support for sem_timedwait to support CLOCK_MONOTONIC time source
Short answer: no.
But you could implement one if you're not using a 3rd party library or C++11 and don't need cross-platform compatibility:
#include <cstring> // memset
#include <ctime> // DEV_NOTE: some systems might need -lrt
#include <csignal> // DEV_NOTE: csignal contains a reference to CLOCK_MONOTONIC
#include <semaphore.h>
#if !defined(CLOCK_MONOTONIC)
#error CLOCK_MONOTONIC is not defined
#endif
typedef struct timespec tick_t;
static tick_t monotonic_tick()
{
tick_t tmp;
if (clock_gettime(CLOCK_MONOTONIC, &tmp) != 0) {
std::memset(&tmp, 0, sizeof(tick_t));
// error, throw std::exception(std::strerror(errno))
}
return tmp;
}
static double elapsed_us(tick_t init, tick_t end)
{
return ((end.tv_sec - init.tv_sec) * 1000000) + (static_cast<double>((end.tv_nsec - init.tv_nsec)) / 1000);
}
static double elapsed_ms(tick_t init)
{
return (elapsed_us(init, monotonic_tick()) / 1000);
}
static int sem_timed_wait(sem_t& sem, unsigned long timeout_ms)
{
if (timeout_ms == 0) {
if (sem_trywait(&sem) == 0) {
return 0;
}
} else {
tick_t start = monotonic_tick();
do {
if (sem_trywait(&sem) == 0) {
return 0;
}
} while (elapsed_ms(start) <= timeout_ms);
}
return -1;
}
Then to use it:
#include <iostream>
#include <pthread.h>
void* thread_fn(void* val)
{
sem_t* sem = static_cast<sem_t*>(val);
std::cout << std::endl << pthread_self() << " thread started" << std::endl;
if (sem_timed_wait(*sem, 1000) == 0) {
std::cout << std::endl << pthread_self() << " got it, sleeping 2 seconds..." << std::endl;
sleep(2); // sleep 2 seconds
std::cout << pthread_self() << " returning..." << std::endl;
// don't forget to release since we acquired the lock
sem_post(sem);
} else {
std::cout << pthread_self() << " timeout" << std::endl;
}
std::cout << pthread_self() << " thread returning" << std::endl;
return NULL;
}
int main(int argc, char* argv[])
{
sem_t sem;
pthread_t t1, t2;
sem_init(&sem, 0, 1); // binary semaphore
std::cout << "Creating..." << std::endl;
pthread_create(&t1, NULL, thread_fn, static_cast<void*>(&sem));
pthread_create(&t2, NULL, thread_fn, static_cast<void*>(&sem));
std::cout << "Joining..." << std::endl;
pthread_join(t1, NULL);
pthread_join(t2, NULL);
std::cout << "Leaving..." << std::endl;
return 0;
}
The above works on a wide array of *nix systems to include the BSD line. If you need a cross platform way of doing this, Windows and Apple have simpler mechanisms to do this.
Hope that can help.
Had the same problem with POSIX system,
Based on C++0x has no semaphores? How to synchronize threads?
and How do I deal with the system clock changing while waiting on a std::condition_variable? and Halûk Uçar answer
#include <stdio.h>
#include <thread>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
class semaphore
{
private:
pthread_mutex_t m_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_condattr_t m_attr;
pthread_cond_t m_cond;
unsigned long count_ = 0;
public :
void init_sem()
{
int result = 0;
result = pthread_condattr_init(&m_attr);
result = pthread_condattr_setclock(&m_attr, CLOCK_MONOTONIC);
result = pthread_cond_init(&m_cond, &m_attr);
}
void notify() {
pthread_mutex_lock(&m_mutex);
++count_;
pthread_cond_signal(&m_cond);
pthread_mutex_unlock(&m_mutex);
}
void wait() {
pthread_mutex_lock(&m_mutex);
while (!count_) // Handle spurious wake-ups.
{
pthread_cond_wait(&m_cond, &m_mutex);
}
--count_;
pthread_mutex_unlock(&m_mutex);
}
void wait_for(int sec)
{
int rc = 0;
pthread_mutex_lock(&m_mutex);
if (!count_)
{
timespec tsTimeout;
clock_gettime(CLOCK_MONOTONIC, &tsTimeout);
// update time calculation to your specific case
tsTimeout.tv_sec += time;
// Handle spurious wake-ups.
while (!count_ && (rc == 0))
{
rc = pthread_cond_timedwait(&m_cond, &m_mutex, &tsTimeout);
}
}
if (rc == 0)
{
printf("success\n");
--count_;
}
else if (rc == ETIMEDOUT)
{
printf("timeout\n");
}
else
{
printf("error\n");
}
pthread_mutex_unlock(&m_mutex);
}
bool destroy()
{
return ((pthread_cond_destroy(&m_cond) == 0)
&& (pthread_mutex_destroy(&m_mutex) == 0)
&& (pthread_condattr_destroy(&m_attr)==0)) ? true : false;
}
};
You can implement your own semaphore routines by using
pthread_cond_signal() for sem_post()
pthread_cond_timedwait() for sem_timedwait()
pthread_cond_wait() for sem_wait()
pthread_cond_timedwait() at current time for sem_trywait()
Of course semaphore creation and deletion will include malloc and free, where you alloc a struct with all parameters (mutex, condition, ... ) needed for your semaphore implementation.
If anyone stumbles across this in the future:
glibc has now implemented this (since version 2.30):
https://www.gnu.org/software/libc/manual/html_node/Waiting-with-Explicit-Clocks.html
you can use sem_clockwait with CLOCK_MONOTONIC.

using timer and signal instead of sleep c/c++

I am working on multi threaded code, in which thread has to sleep for particular time. I don't want to wast CPU cycles and want to / have to use timers. This is more or less what I want achieve.
My single threaded code seems to be working fine.
#include <cstdlib>
#include <iostream>
#include <time.h>
#include <sys/siginfo.h>
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t print_flag = false;
void handle_alarm(int sig)
{
print_flag = true;
}
int main(int argc, char *argv[])
{
//struct sigevent event;
signal( SIGALRM, handle_alarm ); // Install handler first,
timer_t timerid;
struct itimerspec timer;
timer_create(CLOCK_REALTIME,NULL,&timerid);
timer.it_value.tv_sec = 1;
timer.it_value.tv_nsec = 0;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_sec = 0;
std::cout << "Setting timer" << std::endl;
timer_settime(timerid,0,&timer,NULL);
pause();
std::cout << "Hello\n" << std::endl;
return EXIT_SUCCESS;
}
But my multi threaded is stuck in execution. My main thread is stuck at waiting for threads and thread1 is stuck at setting timer. Any idea why thread1 is not completing execution?
#include <cstdlib>
#include <iostream>
#include <time.h>
#include <sys/siginfo.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
volatile sig_atomic_t print_flag = false;
void handle_alarm(int sig)
{
print_flag = true;
}
void *mythread(void* time)
{
signal( SIGALRM, handle_alarm ); // Install handler first,
timer_t timerid;
struct itimerspec timer;
timer_create(CLOCK_REALTIME,NULL,&timerid);
timer.it_value.tv_sec = *(int*)time;
timer.it_value.tv_nsec = 0;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_sec = 0;
std::cout << "Setting timer" << std::endl;
timer_settime(timerid,0,&timer,NULL);
pause();
std::cout << "Hello" << *(int*)time << std::endl;
}
int main(int argc, char *argv[])
{
pthread_t thread1, thread2;
std::cout << "Started threads\n" << std::endl;
int temp1 = 10,temp2 = 5;
pthread_create(&thread1, NULL, &mythread,(void*) &temp1);
pthread_create(&thread2, NULL, &mythread,(void*) &temp2);
std::cout << "Waiting for threads\n" << std::endl;
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
std::cout << "Done\n" << std::endl;
return EXIT_SUCCESS;
}
Edit:
I did it by few methods,
by using nanosleep, it just overcomes one problem, busy wait.
using clock_nanosleep, it is similar to nanosleep except it uses relative clock
Using timer_settime (pulse), the thread waits for pulse for given time and finally clocks out
I did it like this
struct sigevent event;
struct itimerspec itime;
timer_t timer_id;
int chid, rcvid;
my_message_t msg;
chid = ChannelCreate(0);
// following code is used to get kick every pulse period time
// which is 20ms
event.sigev_notify = SIGEV_PULSE;
event.sigev_coid = ConnectAttach(ND_LOCAL_NODE, 0,
chid,
_NTO_SIDE_CHANNEL, 0);
event.sigev_priority = getprio(0);
event.sigev_code = _PULSE_CODE_MINAVAIL;
timer_create(CLOCK_REALTIME, &event, &timer_id);
// 20 ms to nano seconds
itime.it_value.tv_sec = 0;
itime.it_value.tv_nsec = 20000000;
itime.it_interval.tv_sec = 0;
itime.it_interval.tv_nsec = 20000000;
timer_settime(timer_id, 0, &itime, NULL);
SERVO1DELAY1.tv_sec = 0;
SERVO1DELAY1.tv_nsec = 100000;
while(1)
{
rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL);
if (rcvid == 0)
{
// make pulse high for appropriate time
out8( data_handle_A, HIGH );
InterruptDisable();
nanospin(&SERVO1DELAY1);
InterruptEnable();
out8( data_handle_A, LOW );
}
}

the magic cout that keep my program alive

I wrote a code to implement spin lock and mutex lock.
There is an interesting but. A magic cout can keep my program alive. If I remove the cout, my program will be sleeping forever. (This only happens in Linux. Windows is doing fine)
Any one have a clue?
#include <pthread.h>
#include <iostream>
#include <queue>
#include <sys/time.h>
#include <stdexcept>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define Tcount 10
#define TheLock MutexLock
static inline int TAS(volatile int * ptr) {
unsigned long result;
asm volatile("lock;"
"xchgl %0, %1;"
: "=r"(result), "=m"(*ptr)
: "0"(1), "m"(*ptr)
: "memory");
return result;
}
class SpinLock {
private:
int lock;
pthread_t owner;
public:
SpinLock() {
lock = 0;
}
void getLock() {
while (TAS(&lock) == 1) {
}
owner = pthread_self();
}
void releaseLock() {
if (lock == 0) {
cout << "Spin no lock" << endl;
return;
} else if (owner == pthread_self()) {
owner = NULL;
lock = 0;
} else {
throw runtime_error("Spin can't release");
}
}
};
class MutexLock {
private:
int lock;
pthread_t owner;
queue<pthread_t> q;
SpinLock qLock;
public:
MutexLock() {
lock = 0;
}
void getLock(int id) {
pthread_t self = pthread_self();
cout<<"a"<<endl;// magic cout
if (TAS(&lock) == 0) {
owner = self;
return;
}
qLock.getLock();
q.push(self);
qLock.releaseLock();
while (owner != self) {
}
}
void releaseLock(int id) {
if (lock == 0) {
cout << "Mutex no lock" << endl;
return;
} else if (owner == pthread_self()) {
qLock.getLock();
if (q.empty()) {
owner = NULL;
lock = 0;
} else {
owner = q.front();
q.pop();
}
qLock.releaseLock();
} else {
throw runtime_error("Mutex can't release");
}
}
};
TheLock lock;
int g = 0;
void* run(void* pt) {
int id = (int) pt;
for (int i = 0; i < 10000; i++) {
lock.getLock(id);
//cout<<"Thread "<<id<<" get lock, g="<<g<<endl;
int next = g + 1;
g = next;
//cout<<"Thread "<<id<<" release lock, g="<<g<<endl;
lock.releaseLock(id);
}
return NULL;
}
int main() {
pthread_t th[Tcount];
long mtime, seconds, useconds;
struct timeval start, end;
gettimeofday(&start, NULL);
for (int i = 0; i < Tcount; i++) {
pthread_create(&th[i], NULL, run, (void*) (i+10));
}
for (int i = 0; i < Tcount; i++) {
pthread_join(th[i], 0);
}
gettimeofday(&end, NULL);
seconds = end.tv_sec - start.tv_sec;
useconds = end.tv_usec - start.tv_usec;
mtime = ((seconds) * 1000000 + useconds);
cout << "g=" << g << endl;
cout << "time=" << mtime << endl;
return 0;
}
You cannot implement a mutex by using the volatile keyword as the operations may not be atomic. This means that the OS might switch to a different thread before the operation has completed.
For mutex you have to use the OS. It is the only thing that knows when threads are being switched.