using timer and signal instead of sleep c/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 );
}
}

Related

wait() for thread made via clone?

I plan on rewriting this to assembly so I can't use c or c++ standard library. The code below runs perfectly. However I want a thread instead of a second process. If you uncomment /*CLONE_THREAD|*/ on line 25 waitpid will return -1. I would like to have a blocking function that will resume when my thread is complete. I couldn't figure out by looking at the man pages what it expects me to do
#include <sys/wait.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
int globalValue=0;
static int childFunc(void*arg)
{
printf("Global value is %d\n", globalValue);
globalValue += *(int*)&arg;
return 31;
}
int main(int argc, char *argv[])
{
auto stack_size = 1024 * 1024;
auto stack = (char*)mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (stack == MAP_FAILED) { perror("mmap"); exit(EXIT_FAILURE); }
globalValue = 5;
auto pid = clone(childFunc, stack + stack_size, /*CLONE_THREAD|*/CLONE_VM|CLONE_SIGHAND|SIGCHLD, (void*)7);
sleep(1); //So main and child printf don't collide
if (pid == -1) { perror("clone"); exit(EXIT_FAILURE); }
printf("clone() returned %d\n", pid);
int status;
int waitVal = waitpid(-1, &status, __WALL);
printf("Expecting 12 got %d. Expecting 31 got %d. ID=%d\n", globalValue, WEXITSTATUS(status), waitVal);
return 0;
}
If you want to call functions asynchronously with threads I recommend using std::async. Example here :
#include <iostream>
#include <future>
#include <mutex>
#include <condition_variable>
int globalValue = 0; // could also have been std::atomic<int> but I choose a mutex (to also serialize output to std::cout)
std::mutex mtx; // to protect access to data in multithreaded applications you can use mutexes
int childFunc(const int value)
{
std::unique_lock<std::mutex> lock(mtx);
globalValue = value;
std::cout << "Global value set to " << globalValue << "\n";
return 31;
}
int getValue()
{
std::unique_lock<std::mutex> lock(mtx);
return globalValue;
}
int main(int argc, char* argv[])
{
// shared memory stuff is not needed for threads
// launch childFunc asynchronously
// using a lambda function : https://en.cppreference.com/w/cpp/language/lambda
// to call a function asynchronously : https://en.cppreference.com/w/cpp/thread/async
// note I didn't ues the C++ thread class, it can launch things asynchronously
// however async is both a better abstraction and you can return values (and exceptions)
// to the calling thread if you need to (which you do in this case)
std::future<int> future = std::async(std::launch::async, []
{
return childFunc(12);
});
// wait until asynchronous function call is complete
// and get its return value;
int value_from_async = future.get();
std::cout << "Expected global value 12, value = " << getValue() << "\n";
std::cout << "Expected return value from asynchronous process is 31, value = " << value_from_async << "\n";
return 0;
}

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

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;
}

POSIX semaphore doesn't work under high contention/load

Using C++11 on Linux kernel 4.4.0-57, I'm trying to run two busy-looping processes (say p1, p2) pinned (pthread_setaffinity_np) on the same core and making sure the interleaving execution order by using POSIX semaphore (semaphore.h) and sched_yield(). But it did not work out well.
Below is the parent code (parent-task) that spawns 2 processes and each executes child-task code.
#include <stdio.h>
#include <cstdlib>
#include <errno.h> // errno
#include <iostream> // cout cerr
#include <semaphore.h> // semaphore
#include <fcntl.h> // O_CREAT
#include <unistd.h> // fork
#include <string.h> // cpp string
#include <sys/types.h> //
#include <sys/wait.h> // wait()
int init_semaphore(){
std::string sname = "/SEM_CORE";
sem_t* sem = sem_open ( sname.c_str(), O_CREAT, 0644, 1 );
if ( sem == SEM_FAILED ) {
std::cerr << "sem_open failed!\n";
return -1;
}
sem_init( sem, 0, 1 );
return 0;
}
// Fork and exec child-task.
// Return pid of child
int fork_and_exec( std::string pname, char* cpuid ){
int pid = fork();
if ( pid == 0) {
// Child
char* const params[] = { "./child-task", "99", strdup( pname.c_str() ), cpuid, NULL };
execv( params[0], params );
exit(0);
}
else {
// Parent
return pid;
}
}
int main( int argc, char* argv[] ) {
if ( argc <= 1 )
printf( "Usage ./parent-task <cpuid> \n" );
char* cpuid = argv[1];
std::string pnames[2] = { "p111", "p222" };
init_semaphore();
int childid[ 2 ] = { 0 };
int i = 0;
for( std::string pname : pnames ){
childid[ i ] = fork_and_exec( pname, cpuid );
}
for ( i=0; i<2; i++ )
if ( waitpid( childid[i], NULL, 0 ) < 0 )
perror( "waitpid() failed.\n" );
return 0;
}
The child-task code looks like this:
#include <cstdlib>
#include <stdio.h>
#include <sched.h>
#include <pthread.h>
#include <stdint.h>
#include <errno.h>
#include <semaphore.h>
#include <iostream>
#include <sys/types.h>
#include <fcntl.h> // O_CREAT
sem_t* sm;
int set_cpu_affinity( int cpuid ) {
pthread_t current_thread = pthread_self();
cpu_set_t cpuset;
CPU_ZERO( &cpuset );
CPU_SET( cpuid, &cpuset );
return pthread_setaffinity_np( current_thread,
sizeof( cpu_set_t ), &cpuset );
}
int lookup_semaphore() {
sm = sem_open( "/SEM_CORE", O_RDWR );
if ( sm == SEM_FAILED ) {
std::cerr << "sem_open failed!" << std::endl ;
return -1;
}
}
int main( int argc, char* argv[] ) {
printf( "Usage: ./child-task <PRIORITY> <PROCESS-NAME> <CPUID>\n" );
printf( "Setting SCHED_RR and priority to %d\n", atoi( argv[1] ) );
set_cpu_affinity( atoi( argv[3] ) );
lookup_semaphore();
int res;
uint32_t n = 0;
while ( 1 ) {
n += 1;
if ( !( n % 1000 ) ) {
res = sem_wait( sm );
if( res != 0 ) {
printf(" sem_wait %s. errno: %d\n", argv[2], errno);
}
printf( "Inst:%s RR Prio %s running (n=%u)\n", argv[2], argv[1], n );
fflush( stdout );
sem_post( sm );
sched_yield();
}
sched_yield();
}
sem_close( sm );
}
In the child-task code, I have if ( !( n % 1000 ) ) to experiment reducing the contention/load in waiting and posting the semaphore. The outcome I got is that when n % 1000, one of the child process will be always in Sleep state (from top) and the other child process executes properly. However, if I set n % 10000, i.e. less load/contention, both processes will run and printout the output interleavingly which is my expected outcome.
Does anyone know if this is the limitaion of semaphore.h or there's a better way to ensure processes execution order?
Updated: I did a simple example with threads and semaphore, note that sched_yield may help avoiding unnecessary wakeups of the thread that is not 'in turn' to do work, but yielding is not a guarantee. I also show an example with mutex/condvar that is guaranteed to work, no yield necessary.
#include <stdexcept>
#include <semaphore.h>
#include <pthread.h>
#include <thread>
#include <iostream>
using std::thread;
using std::cout;
sem_t sem;
int count = 0;
const int NR_WORK_ITEMS = 10;
void do_work(int worker_id)
{
cout << "Worker " << worker_id << '\n';
}
void foo(int work_on_odd)
{
int result;
int contention_count = 0;
while (count < NR_WORK_ITEMS)
{
result = sem_wait(&sem);
if (result) {
throw std::runtime_error("sem_wait failed!");
}
if (count % 2 == work_on_odd)
{
do_work(work_on_odd);
count++;
}
else
{
contention_count++;
}
result = sem_post(&sem);
if (result) {
throw std::runtime_error("sem_post failed!");
}
result = sched_yield();
if (result < 0) {
throw std::runtime_error("yield failed!");
}
}
cout << "Worker " << work_on_odd << " terminating. Nr of redundant wakeups from sem_wait: " <<
contention_count << '\n';
}
int main()
{
int result = sem_init(&sem, 0, 1);
if (result) {
throw std::runtime_error("sem_init failed!");
}
thread t0 = thread(foo, 0);
thread t1 = thread(foo, 1);
t0.join();
t1.join();
return 0;
}
Here is one way to do it with condition variables and mutexes. Translating from C++ std threads to pthreads should be trivial. To do it between processes, you would have to use a pthread mutex type that can be shared between processes. Maybe the condvar and the mutex can both be placed in shared memory, to achieve the same thing I do below with threads.
See also the manpage pthread_condattr_setpshared (3) or
http://manpages.ubuntu.com/manpages/wily/man3/pthread_condattr_setpshared.3posix.html
On the other hand, maybe it is simpler to just use a SOCK_STREAM unix domain socket between the two worker processes, and just block on the socket until the peer worker pings you (i.e. send one char) over the socket.
#include <cassert>
#include <iostream>
#include <thread>
#include <condition_variable>
#include <unistd.h>
using std::thread;
using std::condition_variable;
using std::mutex;
using std::unique_lock;
using std::cout;
condition_variable cv;
mutex mtx;
int count;
void dowork(int arg)
{
std::thread::id this_id = std::this_thread::get_id();
cout << "Arg: " << arg << ", thread id: " << this_id << '\n';
}
void tfunc(int work_on_odd)
{
assert(work_on_odd < 2);
auto check_can_work = [&count, &work_on_odd](){ return ((count % 2) ==
work_on_odd); };
while (count < 10)
{
unique_lock<mutex> lk(mtx);
cv.wait (lk, check_can_work);
dowork(work_on_odd);
count++;
cv.notify_one();
// Lock is unlocked automatically here, but with threads and condvars,
// it is actually better to unlock manually before notify_one.
}
}
int main()
{
count = 0;
thread t0 = thread(tfunc, 0);
thread t1 = thread(tfunc, 1);
sleep(1);
cv.notify_one();
t0.join();
t1.join();
}

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.

SIGALRM kills process

I have a trouble with SIGALRM. I am using it to write pids of active processes every 3 seconds.
But after it fires once it kills main process. What did I do wrong?
I am also using signals to kill each of child processes after some time, I am using SIGTERM there.
It wors just fine until I add this part to list active processes. Even after killing main one the others are still going.
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <signal.h>
#include <time.h>
#include <map>
using namespace std;
////DARK SORROW PLACE////////////////////////////
#define CHLD_DELAY 3
std::map<pid_t, bool> pidy;
/////////////////////////////////////////////////
void sweetDreams(int sec, int nanosec)
{
timespec ttw;
ttw.tv_sec = sec;
ttw.tv_nsec = nanosec;
while( nanosleep( &ttw, &ttw) && ( errno != EINTR ) ) continue;
}
//////////////////////////////////////////////////
void ns(long int ns, timespec *ts)
{
ts->tv_sec = (time_t)ns/1000000000;
ts->tv_nsec = (long)(ns - ts->tv_sec*1000000000);
}
//////////////////////////////////////////////////
class Order
{
public:
char* table;
int start;
int step;
int shift;
long int dt;
long int dieAfter;
};
////////////////////////////////////////////////////
void killer(int sig, siginfo_t *siginfo, void *context)
{
// kill(siginfo->si_pid, NULL);
_exit(0);
}
////////////////////////////////////////////////////
void carefullDad(int sig)
{
cout << "lista zywych dzieci:\n-----------------------" << endl;
for(auto i : pidy)
{
if( i.second ) cout << i.first << endl;
}
cout << "-----------------------" << endl;
}
////////////////////////////////////////////////////
int main(int argc, char** argv)
{
char test[] = { 't', 'e', 's', 't' };
Order orderArr[2] = {
{test, 0, 2, 0, 1000000000L, 10000000000L},
{test, 1, 3, -32 , 2000000000L, 6000000000L}
};
//pid_t pidArr[sizeof(orderArr) / sizeof(Order)];
pid_t wpid;
int status = 0;
struct sigevent st;
// memset(&st, 0, sizeof(st));
st.sigev_notify = SIGEV_SIGNAL;
st.sigev_signo = SIGALRM;
struct itimerspec it;
//memset(&it, 0, sizeof(it));
it.it_value = { CHLD_DELAY,0L};
it.it_interval = {CHLD_DELAY,0L};
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_handler = carefullDad;
sigaction(SIGALRM, &act, NULL);
timer_t timer;
timer_create( CLOCK_REALTIME, &st, &timer);
timer_settime(timer, 0, &it, NULL);
for(Order ord : orderArr)
{
// static int i = 0;
pid_t pid = fork();
if(pid == -1)
{
cerr << "Blad!!!" << endl;
exit(1);
}
if(!pid)
{
//some code here
//end rest is here
You forgot to set act.sa_flags.
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_handler = carefullDad;
act.sa_flags = 0;
sigaction(SIGALRM, &act, NULL);
When you set the signal handler it probably had the SA_RESETHAND flag set.
Either ignore the SIGALRM using sigprocmask() or install a valid handler using sigaction().
For everyone encountering this problem in the future.
You need to set:
struct sigaction act;
act.sa_handler = carefullDad;
act.sa_flags = SA_RESTART;
sigaction(SIGALRM, &act, NULL);