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);
Related
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;
}
I have learned recently about processes and threads, and I am building a project where I need to run a program inside a child process.
The problem is that after the program in the child process exits I don't know how to restart and run the program again.
Here's a test which demonstrates what I am trying to do.
main.cpp file:
#include <iostream>
#include <unistd.h>
#include <sys/ptrace.h>
#include "handler.h"
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "usage: program name" << std::endl;
return 1;
}
pid_t pid = fork();
if (pid == 0)
{
if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) < 0)
std::cerr << "ptrace error" << std::endl;
else
execl(argv[1], argv[1], nullptr);
}
else if (pid >= 1)
{
Handler handler(std::string(argv[1]), pid);
handler.run();
}
}
handler.h file:
#include <stdio.h>
#include <unistd.h>
#include <string>
#include <sys/ptrace.h>
#include <sys/wait.h>
class Handler
{
private:
pid_t m_pid;
std::string m_name;
public:
Handler(const std::string& name, pid_t pid) : m_name(name), m_pid(pid)
{
}
void run()
{
std::string line;
while (true)
{
std::cout << "(command) ";
std::getline(std::cin, line);
if (line == "run")
{
int options = 0, status = 0;
ptrace(PTRACE_CONT, m_pid, nullptr, nullptr);
int pid = waitpid(m_pid, &status, options);
// trying to restart again the program
if (pid < 0)
{
m_pid = fork();
execl(m_name.c_str(), m_name.c_str(), nullptr);
}
}
}
}
};
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 );
}
}
why is not possible to have a multiple timer with single handler. I used the program from the below link and it is not working. He has explained the reason about the problem but it is not very clear. Is someone help me why is it not working ??
http://www.graphics-muse.org/wp/?p=868
There is no reason you can't have multiple timers created with timer_create using the same handler, provided your sigval structure contains enough information to distinguish between them as needed in your handler.
The point of the article is that it is possible to have multiple timers trigger the same handler but you need to differentiate them based on some passed data. Oddly the example the author used only went 3/4th of the distance of illustrating this in the code so maybe that is the source of your confusion.
Hopefully this reworking of the article's program is a bit clearer. It uses the sival_ptr to point to a string but it can point to any type. This is how the timers are differentiated.
#define _POSIX_C_SOURCE 199309
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
void timerHandler( int sig, siginfo_t *si, void *uc )
{
// obligator caution not to use printf and other async-unsafe calls
// in a handler in real programs
printf("I am timer %s\n", (char *) si->si_value.sival_ptr);
}
void makeTimer(char *name, int intervalMS)
{
struct sigevent te;
struct itimerspec its;
struct sigaction sa;
int sigNo = SIGRTMIN;
// Set up signal handler.
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = timerHandler;
sigemptyset(&sa.sa_mask);
if (sigaction(sigNo, &sa, NULL) == -1)
errExit("sigaction");
// Set up timer
te.sigev_notify = SIGEV_SIGNAL;
te.sigev_signo = sigNo;
te.sigev_value.sival_ptr = name;
timer_t timerID;
if (timer_create(CLOCK_REALTIME, &te, &timerID) == -1)
errExit("timer_create");
its.it_value.tv_sec = intervalMS;
its.it_value.tv_nsec = 0;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
if (timer_settime(timerID, 0, &its, NULL) == -1)
errExit("timer_settime");
return;
}
int main(int argc, char *argv[])
{
char *arr[3] = {"number one", "number two", "number three"};
makeTimer(arr[0], 1);
makeTimer(arr[1], 2);
makeTimer(arr[2], 3);
while (sleep(5));
return(0);
}
// windows_procon.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <windows.h>
#include <process.h>
using namespace std;
HANDLE mutex;
HANDLE emptySlots;
HANDLE filledSlots;
#define BUFFER_SIZE 10
void *producer(void *);
void *consumer(void *);
int produceItem(void);
void printBuffer(void);
int buffer[BUFFER_SIZE];
int head = 0;
int tail = 0;
int _tmain(int argc, _TCHAR* argv[])
{
DWORD prodThrdID, consThrdID;
mutex = CreateMutex(NULL,FALSE,NULL);
emptySlots = CreateSemaphore(NULL,BUFFER_SIZE,BUFFER_SIZE,NULL);
filledSlots = CreateSemaphore(NULL,0,0,NULL);
srand(time(NULL));
_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void*))producer,
0, 0, (unsigned int *)&prodThrdID);
_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void*))consumer,
0, 0, (unsigned int *)&consThrdID);
return 0;
}
void *producer(void *n)
{
int item;
for(int i = 0; i <BUFFER_SIZE+5; i++)
{
WaitForSingleObject(emptySlots,INFINITE);
WaitForSingleObject(mutex,INFINITE);
item = produceItem();
//printf("Producing");
cout << "Producing: " << item << endl;
//logfile << "Producing: "<< item << endl;
//fprintf(logfile, "Producing: %d \n", item);
buffer[head] = item;
head = (head + 1) % BUFFER_SIZE;
printBuffer();
ReleaseMutex(mutex);
ReleaseSemaphore(filledSlots,1, NULL);
}
return n;
}
void *consumer(void *n)
{
for(int i = 0; i <BUFFER_SIZE+5; i++)
{
WaitForSingleObject(filledSlots,INFINITE);
//Sleep(500);
WaitForSingleObject(mutex,INFINITE);
cout << "Consuming: " << buffer[tail] << endl;
buffer[tail] = 0;
tail = (tail + 1) % BUFFER_SIZE;
printBuffer();
ReleaseMutex(mutex);
ReleaseSemaphore(emptySlots,1, NULL);
}
return n;
}
int produceItem(void)
{
int x = (rand()%11 + 1);
return x;
}
void printBuffer(void)
{
for(int i = 0; i <BUFFER_SIZE; i++)
{
printf("%d ", buffer[i]);
}
printf("END \n");
}
My program here is supposed to be an algorithm for the producer-consumer problem. I think I have the algorithm correct my only problem is that I'm having trouble getting the threads to run properly. Can someone tell me what the issue is?
You need to wait for the threads you create with _beginthreadex to do their work, as it stands you program will exit immediately after creating them. I haven't looked any further at you logic.
Here is an example.
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );
WaitForSingleObject( hThread, INFINITE );