How to implement 2 timers in linux - c

I m trying to set the flag variable on(working with raspbery pi. I need pin on) for 500 useconds(micro seconds) and flag off for 300 useconds continuously(infinitely until I stop it). I thought of implementing it using 2 timers.
Now In this program i have written for 5 seconds and 3 seconds.
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
struct sigaction sa;
struct itimerval timer1,timer2;
int count=1;
void timer_handler (int signum)
{
if(count++%2==1)
printf("High\n"); //flag=1
else
printf("Low\n"); //flag=0
}
int main ()
{
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sa.sa_flags = SA_RESTART;
sigaction (SIGALRM, &sa, NULL);
int i=0;
while(1){
scanf(" %d",&i);
if(i==1){ // I m starting 2 timers here
timer1.it_value.tv_sec = 0;
timer1.it_value.tv_usec = 1;
timer1.it_interval.tv_sec = 8; //5+3
timer1.it_interval.tv_usec = 0;
timer2.it_value.tv_sec = 5;
timer2.it_value.tv_usec = 0;
timer2.it_interval.tv_sec = 8;
timer2.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer1, NULL);
setitimer (ITIMER_REAL, &timer2, NULL);
}
else if(i==2) // I m stopping here
{
timer1.it_value.tv_sec = 0;
timer1.it_value.tv_usec = 0;
timer1.it_interval.tv_sec = 0;
timer1.it_interval.tv_usec = 0;
timer2.it_value.tv_sec = 0;
timer2.it_value.tv_usec = 0;
timer2.it_interval.tv_sec = 0;
timer2.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer1, NULL); // 1st timer on
setitimer (ITIMER_REAL, &timer2, NULL); //2nd timer on
}
}
}
This is code I have written.
what actually happening is the second timer is running and first timer is not running. I think its overwritten.
Ps. I dont want to use sleep function as it takes more time. I m using timers as the resolution is microsecond.
1.How do I do this using two timers?
2.Is there any better method to do this task?

There is only one ITIMER_REAL, so you must create virtual timers yourself. A simple and reliable possibility if you don't need microsecond precision, is to use a periodic timer with a small interval and implement your virtual timers on top of that (so every "tick" from your periodic timer will decrement your virtual timers).
Following an example how you could implement it:
vtimer.h
#ifndef VTIMER_H
#define VTIMER_H
typedef void (vtimer_timeout)(void *arg);
typedef struct vtimer
{
int msec;
int periodic;
int current;
vtimer_timeout *timeout;
} vtimer;
#define vtimer_init(m, p, cb) { \
.msec=(m), .periodic=(p), .current=0, .timeout=cb}
void vtimer_start(vtimer *self, void *timeoutArg);
void vtimer_stop(vtimer *self);
// call this periodically, e.g. after each interrupted library call:
void vtimer_dispatch();
#endif
vtimer.c
#define _POSIX_C_SOURCE 200101L
#include "vtimer.h"
#include <stddef.h>
#include <signal.h>
#include <sys/time.h>
#define NUM_TIMERS 8
static vtimer *timers[NUM_TIMERS] = {0};
static void *timoutArgs[NUM_TIMERS] = {0};
static size_t ntimers = 0;
static volatile sig_atomic_t ticks = 0;
static void tickhandler(int signum)
{
(void)signum;
++ticks;
}
static struct sigaction timerAction = {.sa_handler = tickhandler};
static struct sigaction defaultAction;
static struct itimerval tickTimerval = {{0, 1000}, {0, 1000}};
static struct itimerval disableTimerval = {{0,0},{0,0}};
void vtimer_start(vtimer *self, void *timeoutArg)
{
int found = 0;
for (size_t idx = 0; idx < NUM_TIMERS; ++idx)
{
if (timers[idx] == self)
{
found = 1;
break;
}
}
if (!found)
{
if (ntimers == NUM_TIMERS) return; // or maybe return error
if (!ntimers++)
{
// only start the "ticking" timer when necessary
sigaction(SIGALRM, &timerAction, &defaultAction);
setitimer(ITIMER_REAL, &tickTimerval, 0);
}
for (size_t idx = 0; idx < NUM_TIMERS; ++idx)
{
if (!timers[idx])
{
timers[idx] = self;
timoutArgs[idx] = timeoutArg;
break;
}
}
}
self->current = self->msec;
}
void vtimer_stop(vtimer *self)
{
int found = 0;
for (size_t idx = 0; idx < NUM_TIMERS; ++idx)
{
if (timers[idx] == self)
{
timers[idx] = 0;
found = 1;
break;
}
}
if (found && !--ntimers)
{
// no virtual timers running -> stop ticking timer
setitimer(ITIMER_REAL, &disableTimerval, 0);
sigaction(SIGALRM, &defaultAction, 0);
}
}
void vtimer_dispatch(void)
{
while (ticks)
{
--ticks;
for (size_t idx = 0; idx < NUM_TIMERS; ++idx)
{
if (timers[idx])
{
if (!--(timers[idx]->current))
{
timers[idx]->timeout(timoutArgs[idx]);
if (timers[idx]->periodic)
{
timers[idx]->current = timers[idx]->msec;
}
else vtimer_stop(timers[idx]);
}
}
}
}
}
Example program using this:
#include "vtimer.h"
#include <stdio.h>
#include <errno.h>
static void timer1_timeout(void *arg)
{
(void) arg;
puts("timer 1");
}
static void timer2_timeout(void *arg)
{
(void) arg;
puts("timer 2");
}
int main(void)
{
vtimer timer1 = vtimer_init(5000, 1, timer1_timeout);
vtimer timer2 = vtimer_init(8000, 1, timer2_timeout);
vtimer_start(&timer1, 0);
vtimer_start(&timer2, 0);
for (;;)
{
errno = 0;
int c = getchar();
if (c == EOF && errno != EINTR) break;
if (c == 'q') break;
vtimer_dispatch();
}
vtimer_stop(&timer2);
vtimer_stop(&timer1);
return 0;
}
There are a lot of design decisions on the way (e.g. how frequent your ticks should be (here 1ms), having a fixed number of virtual timers vs a dynamic one, using pointers as "timer handles" or maybe integers, and so on), so think about what you need and try to write your own.

Related

Segmentation fault before main is executed

For some reason I am getting a segmentation fault before any of my code is actually executed in the main() function. I have tried following the line of execution by putting in printfs but nothing is actually executed. I don't see anything in my program that would be causing a stack overflow, as I hardly even use memory.
If someone has better eyes than me and can spot this error it would be very much appreciated!
Main:
#include "../inc/protos.h"
HistogramData *histogram_data;
bool signal_caught = false;
sem_t *semaphore_id;
int letter_count[kLetterCount] = { 0 };
int wait_time = 0;
int main(void)
{
int shared_memory_id = 0;
key_t shared_memory_key = 0;
char buffer[kBufferLength] = { 0 };
int heads = 0;
int tails = 0;
printf("1");
histogram_data->signal_caught = false;
signal(SIGINT, signal_handler);
printf("2");
//Get the key to the allocated shared memory
shared_memory_key = ftok("/tmp", 'M');
if(shared_memory_key == -1)
{
printf("(CONSUMER) Cannot allocate key.\n");
return 1;
}
printf("3");
//Look for shared memory every 10 seconds until it finds it
while(true)
{
if((shared_memory_id = shmget(shared_memory_key, sizeof(histogram_data), 0)) == -1)
{
printf("4");
printf("(CONSUMER) Shared Memory does not exist. Please run the Producer program.\n");
sleep(kSleepTime);
}
else
{
printf("5");
break;
}
}
printf("(CONSUMER) Our Shared Memory ID is %d.\n", shared_memory_id);
//Attach the structure to the shared memory
histogram_data = (HistogramData*) shmat(shared_memory_id, NULL, 0);
if(histogram_data == NULL)
{
printf("(CONSUMER) Cannot attach to Shared Memory.\n");
return 3;
}
semaphore_id = sem_open("/HISTOGRAM_SEM", O_CREAT, S_IRUSR | S_IWUSR, 1);
signal(SIGALRM, alarm_handler);
//Set the watchdog timer to 2 seconds.
alarm(kAlarmSeconds);
//Detach from shared memory
shmdt(histogram_data);
return 0;
}
void signal_handler(int signal_number)
{
printf ("(CONSUMER) Received a signal. SIGINT ID is %d\n", signal_number);
histogram_data->signal_caught = true;
// Send SIGINT to Producer2
kill(histogram_data->producer2_pid, SIGINT);
// Send SIGINT to Producer1
kill(histogram_data->producer1_pid, SIGINT);
}
void print_line(int num)
{
int hundreds = num / 100;
num = num % 100;
int tens = num / 10;
num = num % 10;
int ones = num;
int i = 0;
for(i = 0; i < hundreds; i++)
{
printf("*");
}
for(i = 0; i < tens; i++)
{
printf("+");
}
for(i = 0; i < ones; i++)
{
printf("-");
}
printf("\n");
}
void display_histogram(int letter_count[])
{
int i = 0;
printf("\n********** HISTOGRAM **********\n");
for(i = 0; i < kLetterCount; i++)
{
printf("%c-%03d ", i + 65, letter_count[i]);
print_line(letter_count[i]);
}
}
void alarm_handler(int signal_number)
{
int wait_time = 0;
sem_wait(semaphore_id);
int i = 0;
for(i = 0; i < kDCReads; i++)
{
int* read_index = &histogram_data->read_index;
if(histogram_data->circular_buffer[*read_index] != 0)
{
int read_data = histogram_data->circular_buffer[*read_index];
histogram_data->circular_buffer[*read_index] = 0;
++letter_count[read_data - 65];
if(*read_index == kCircleBufferSize)
{
*read_index = 0;
}
if(*read_index == histogram_data->write_index)
{
break;
}
}
}
if(signal_caught == true)
{
//Read and write indexes from the histogram data structure
int* read_index = &histogram_data->read_index;
int* write_index = &histogram_data->write_index;
//Read data from buffer
while(*read_index != *write_index)
{
if(histogram_data->circular_buffer[*read_index])
{
//Data read in from the circular buffer
int read_data = histogram_data->circular_buffer[*read_index];
//Mark element as read
histogram_data->circular_buffer[*read_index] = 0;
++letter_count[read_data - 65];
//Increment the elements
(*read_index)++;
if(*read_index == 256)
{
*read_index = 0;
}
if(*read_index == *write_index)
{
break;
}
}
}
//Display a histogram listing
display_histogram(letter_count);
return;
}
wait_time++;
if(wait_time >= 5)
{
wait_time = 0;
display_histogram(letter_count);
}
//Release semaphore lock
sem_post(semaphore_id);
//Set the alarm for the watchdog to be two seconds
alarm(kAlarmSeconds);
//Reactivate watchdog signal
signal(signal_number, alarm_handler);
}
protos.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <signal.h>
#include <semaphore.h>
#define kCircleBufferSize 256
#define kBufferLength 126
#define kLetterCount 20
#define kDCReads 60
#define kAlarmSeconds 2
#define kSleepTime 10
typedef struct HistogramData HistogramData;
struct HistogramData
{
int read_index;
int write_index;
int is_wrap_around;
pid_t producer1_pid;
pid_t producer2_pid;
char circular_buffer[kCircleBufferSize];
bool signal_caught;
};
void signal_handler(int signal_number);
void print_line(int num);
void display_histogram(int letter_count[]);
void alarm_handler(int signal_number);
For some reason I am getting a segmentation fault before any of my code is actually executed in the main() function.
One of your preloaded data structures is likely to be causing overflow in the stack. You also have a lot of buffering going on to the output and, additionally, you have several places where you use printf() but do not append the newline \nto flush the console buffer. Alternatively, you can follow #sabbahillel's comment by putting fflush() after your printf() statements.
You create histogram_data as a pointer to HistogramData, but don't create a HistogramData object. Then, when you call histogram_data->signal_caught = false in main, you program dereferences a NULL pointer.
Instead, allocate memory for HistogramData before using the pointer (for example, histogram_data = malloc(sizeof *histogram_data);). Don't forget to free it later, too.

C: Using functions from a separate file

Trying to use a bounded buffer from a separate file that I've coded and it seems like that's where the code goes all crazy. Fairly new to C, and I was wondering if I am using the buffer the right way. The concept of instantiation isn't here, so if I just call one of the functions such as bbuff_blocking_insert will the array get initialized? How do I make the appropriate calls in order to get this working?
candy.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include "bbuff.h"
#include <stdbool.h>
#include <time.h>
_Bool stop_thread = false;
typedef struct {
int source_thread;
double time_stamp_in_ms;
} candy_t;
double current_time_in_ms (void) {
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
return now.tv_sec * 1000.0 + now.tv_nsec/1000000.0;
}
void* createCandy(void* arg) {
int r;
int factoryNumber = *(int*)arg;
while(!stop_thread) {
r = rand() % 4;
printf("Random Number: %d\n", r);
printf("\tFactory %d ship candy & wait %ds\n", factoryNumber, r);
candy_t *candy = (candy_t*)malloc(sizeof(candy_t));
candy->source_thread = factoryNumber;
candy->time_stamp_in_ms = current_time_in_ms();
bbuff_blocking_insert((void *)candy);
sleep(r);
}
printf("Candy-factory %d done\n", factoryNumber);
return 0;
}
void* extractCandy(void* arg) {
int r;
candy_t* candy;
while(true) {
candy = (candy_t*)bbuff_blocking_extract();
printf("Candy Source Thread: %d\n", candy->source_thread);
r = rand() % 2;
sleep(r);
}
return 0;
}
int main(int argc, char* argv[]) {
//Extract Arguments
if (argc <= 1) {
printf("Insufficient Arguments\n");
exit(-1);
}
int NO_FACTORIES = atoi(argv[1]);
int NO_KIDS = atoi(argv[2]);
int NO_SECONDS = atoi(argv[3]);
bbuff_init();
//Spawn Factory Threads
pthread_t ftids[NO_FACTORIES];
int factoryNumber[NO_FACTORIES];
for (int i = 0; i < NO_FACTORIES; i++) {
factoryNumber[i] = i;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ftids[i], &attr, createCandy, &factoryNumber[i]);
}
//Spawn Kid Threads
pthread_t ktids [NO_KIDS];
for (int i = 0; i < NO_KIDS; i++) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ktids[i], &attr, extractCandy, NULL);
}
//Wait for Requested Time
for (int i = 0; i < NO_SECONDS; i++) {
sleep(1);
printf("Time %ds\n", i+1);
}
//Stop Factory Threads
stop_thread = true;
for (int i = 0; i < NO_FACTORIES; i++) {
pthread_join(ftids[i], NULL);
}
//Wait until no more candy
while(bbuff_is_data_available()) {
printf("Waiting for all candy to be consumed");
sleep(1);
}
//Stop kid Threads
for (int i = 0; i < NO_KIDS; i++) {
pthread_cancel(ktids[i]);
pthread_join(ktids[i], NULL);
}
//Print Statistics
//Clean up any allocated memory
return 0;
}
bbuff.h
#ifndef BBUFF_H
#define BBUFF_H
#define QUEUE_SIZE 10
void bbuff_init(void);
void bbuff_blocking_insert(void* item);
void* bbuff_blocking_extract(void);
_Bool bbuff_is_data_available(void);
#endif
bbuff.c
#include "bbuff.h"
pthread_mutex_t mutex;
sem_t empty;
sem_t full;
int in = 0;
int out = 0;
int counter = 0;
void* buffer[QUEUE_SIZE];
void bbuff_init(void){
pthread_mutex_init(&mutex, NULL);
sem_init( &empty, 0, QUEUE_SIZE);
sem_init( &full, 0, 0);
}
void bbuff_blocking_insert(void* item) {
sem_wait(&empty);
pthread_mutex_lock(&mutex);
counter++;
buffer[in] = item;
in = (in+1) % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
void* bbuff_blocking_extract(void) {
void* extractedItem;
sem_wait(&full);
pthread_mutex_lock(&mutex);
counter--;
extractedItem = buffer[out];
buffer[out] = NULL;
out = out % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
return extractedItem;
}
Output
$ ./candykids 1 1 10
Random Number: 3
Factory 0 ship candy & wait 3s
Candy Source Thread: 0
Time 1s
Time 2s
Random Number: 1
Factory 0 ship candy & wait 1s
Time 3s
Segmentation fault (core dumped)
In bbuff_blocking_extract(),
out = out % QUEUE_SIZE;
Should be:
out = (out+1) % QUEUE_SIZE;

Segmentation fault after swapcontext in alarm handler

Basically what I am trying to do is simulate multithreading on a single thread with context switching. I set up an alarm for every 10 microseconds, and I switch the context from one to another thread. The problem is that about one in 5 runs ends up with a seg fault right after the alarm finishes the swapcontext, at least that is where I traced it with gdb.
Here are my source files
main.c
#include "umt.h"
void f()
{
int x = 10;
printf("starting thread\n");
while(x)
{
printf("thread %d\n", x);
sleep(1);
x--;
}
}
int main()
{
int x = 0, y, z;
umt_init();
y = umt_thread_create(f);
printf("starting main\n");
if(y == 0)
{
printf("Problems with creating thread\n");
return;
}
x = 10;
z = 1;
while(x)
{
printf("main\n");
x--;
}
umt_thread_join(y);
printf("done waiting\n");
return 0;
}
UMT.h
#include <sys/time.h>
#include <stdio.h>
#include <signal.h>
#include <ucontext.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
typedef struct _umt_thread
{
int thread_id;
ucontext_t context;
void (*handler)(void);
int hasFinished;
}umt_thread, *pumt_thread;
void umt_init();
int umt_thread_create(void (*handler)(void));
void umt_thread_join(int thr);
and umt.c
#include "umt.h"
#define MAIN_CONTEXT 0
#define STACK_SIZE 1638400
int currentThread;
char threadpool[15];
pumt_thread threads;
void signal_thread_finish();
void thread_handler()
{
threads[currentThread].handler();
signal_thread_finish();
}
void thread_scheduler();
void signal_thread_finish()
{
threads[currentThread].hasFinished = TRUE;
threadpool[currentThread] = 0;
thread_scheduler();
}
void thread_scheduler()
{
int nextThread = 0, curThread = 0;
int x = 0;
ucontext_t *con1, *con2;
nextThread = currentThread + 1;
while(1)
{
if(nextThread == 15)
nextThread = 0;
if(nextThread == currentThread)
break;
if(threadpool[nextThread] == 1)
break;
nextThread++;
}
if(nextThread == currentThread)
return;
curThread = currentThread;
currentThread = nextThread;
con1 = &(threads[curThread].context);
con2 = &(threads[nextThread].context);
x = swapcontext(con1, con2);
}
void umt_init()
{
ucontext_t context;
struct itimerval mytimer;
int i;
stack_t new_stack;
getcontext(&context);
threads = (pumt_thread)malloc(sizeof(umt_thread) * 15);
threads[MAIN_CONTEXT].thread_id = MAIN_CONTEXT;
threads[MAIN_CONTEXT].context = context;
threadpool[MAIN_CONTEXT] = 1;
for(i = 1;i<15;i++)
{
threadpool[i] = 0;
}
currentThread = 0;
new_stack.ss_sp = (char*)malloc(STACK_SIZE);
new_stack.ss_size = STACK_SIZE;
new_stack.ss_flags = 0;
i = sigaltstack(&new_stack, NULL);
if(i != 0)
{
printf("problems assigning new stack for signaling\n");
}
signal(SIGALRM, thread_scheduler);
mytimer.it_interval.tv_sec = 0;
mytimer.it_interval.tv_usec = 10;
mytimer.it_value.tv_sec = 0;
mytimer.it_value.tv_usec = 5;
setitimer(ITIMER_REAL, &mytimer, 0);
}
int umt_thread_create(void (*handler)(void))
{
ucontext_t context;
int i, pos;
for(i = 1;i<15;i++)
{
if(threadpool[i] == 0)
{
pos = i;
break;
}
}
if(i == 15)
{
printf("No empty space in the threadpool\n");
return -1;
}
if(getcontext(&context) == -1)
{
printf("Problems getting context\n");
return 0;
}
context.uc_link = 0;//&(threads[MAIN_CONTEXT].context);
context.uc_stack.ss_sp = (char*)malloc(STACK_SIZE);
if(context.uc_stack.ss_sp == NULL)
{
printf("Problems with allocating stack\n");
}
context.uc_stack.ss_size = STACK_SIZE;
context.uc_stack.ss_flags = 0;
makecontext(&context, thread_handler, 0);
threads[pos].thread_id = pos;
threads[pos].context = context;
threads[pos].handler = handler;
threads[pos].hasFinished = FALSE;
threadpool[pos] = 1;
printf("Created thread on pos %d\n", pos);
return pos;
}
void umt_thread_join(int tid)
{
while(!threads[tid].hasFinished)
{
}
}
I tried a lot of combinations and tried tracing by instruction but could not arrive to a conclusion or idea as to what might cause this seg fault. Thanks
Few issues I see (some are related to segfault + some other comments)
You scheduler (thread_scheduler) should be in a critical section, e.g. you should block any alarm signals (or ignore them) so that the handing of the threadpool is done in a way that doesn't corrupt it. you can either use sigprocmask or a volatile boolean variable that will silence the alarm (note this is not the same as the user threads mutex, just an internal synchronization to your scheduling logic)
your clock ticks way too fast IMHO, this is in micro seconds, not milliseconds, so 1000 microseconds for tv_usec might make more sense for testing purposes.
small stack sizes might also cause a seg fault but it seems your stack is big enough.
p.s. there is a better way to handle join, you currently waste lot's of CPU cycles on it, why not simply avoid switching to a thread that called join, untill the thread that it's waiting for has terminated?

Build a framework using C, and let it have some futures like erlang

I use sigsetjmp/siglongjmp to change the progame stack. This is the demo:
#include <stdio.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#define POOLSIZE 4096
int active = 0;
int total = 0;
struct thread
{
int tid;
sigjmp_buf env;
char buf[4096];
int state;
ssize_t size;
};
struct thread *thread_pool = 0L;
char* anchor_beg = 0L;
char* anchor_end = 0L;
void(*new_thread)(int) = 0L;
void sig_call(int sig)
{
char anchor;
anchor_end = &anchor;
if(sigsetjmp(thread_pool[active].env, 0) == 0)
{
thread_pool[active].size = anchor_beg - anchor_end;
memcpy(thread_pool[active].buf, anchor_end, thread_pool[active].size);
siglongjmp(thread_pool[0].env, 1);
}
else
{
memcpy(anchor_beg - thread_pool[active].size, thread_pool[active].buf, thread_pool[active].size);
}
}
void thread_new(void(*pfn)(int))
{
alarm(0);
new_thread = pfn;
thread_pool[0].state = 2;
// printf("create new thread:%d\n", total + 1);
raise(SIGUSR1);
}
void test(int thread)
{
int i = 0;
for(;i != 1000000; i++)
{
}
}
void thread_main(int thread)
{
int i = 0;
for(i = 0; i < 4000; i++)
thread_new(test);
}
void call(void(*pfn)(int))
{
active = ++ total;
thread_pool[active].tid = active;
thread_pool[active].state = 1;
ualarm(500, 0);
pfn(active);
thread_pool[active].state = 0;
}
void dispatcher()
{
thread_pool = (struct thread*)malloc(sizeof(struct thread) * POOLSIZE);
char anchor;
anchor_beg = &anchor;
thread_pool[0].tid = 0;
thread_pool[0].state = 1;
if(sigsetjmp(thread_pool[0].env, 0) == 0)
{
signal(SIGUSR1, sig_call);
signal(SIGALRM, sig_call);
call(thread_main);
}
else if(thread_pool[0].state == -1)
{
return;
}
else if(thread_pool[0].state == 2)
{
thread_pool[0].state = 1;
call(new_thread);
}
while(1)
{
int i, alive = 0;
for(i = 1; i <= total; i++)
{
if(thread_pool[i].state == 1)
{
alive ++;
ualarm(500, 0);
active = thread_pool[i].tid;
siglongjmp(thread_pool[i].env, 1);
}
}
if(alive == 0)
return;
}
}
int main()
{
dispatcher();
}
Is there any problem here? And when i want to call some third party interface, and maybe it is a block I/O there, can i do something to change another context to execute? and How?
Unfortunately, what you're trying to do doesn't work, because (per the setjmp manual):
The longjmp() routines may not be called after the routine which called
the setjmp() routines returns.
This is because the setjmp/longjmp family of functions (including the sig variants) do not preserve the entire contents of the process stack.

Program required for stopping the signal after certain repetitions

Can anybody provide help to stop the signal after certain repetions .Below is the sample code.
I want that after 3 repetitions the signal should be stopped.But currently it is not stopping:
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <errno.h>
#define INTERVAL 1
int g=0;
int howmany = 0;
void exit_func (int i)
{
signal(SIGTERM,exit_func);
printf("\nBye Bye!!!\n");
exit(0);
}
void alarm_wakeup (int i)
{
struct itimerval tout_val;
g++;
printf("\n %d \n",g);
// signal(SIGALRM,alarm_wakeup);
if(g==3)
{
printf("\n %d \n",g);
signal(SIGSTOP,exit_func);
printf("%s",strerror(errno));
}
howmany += INTERVAL;
printf("\n%d sec up partner, Wakeup!!!\n",howmany);
tout_val.it_interval.tv_sec = 0;
tout_val.it_interval.tv_usec = 0;
tout_val.it_value.tv_sec = INTERVAL; /* 10 seconds timer */
tout_val.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &tout_val,0);
}
int main ()
{
struct itimerval tout_val;
tout_val.it_interval.tv_sec = 0;
tout_val.it_interval.tv_usec = 0;
tout_val.it_value.tv_sec = INTERVAL; /* 10 seconds timer */
tout_val.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &tout_val,0);
signal(SIGALRM,alarm_wakeup); /* set the Alarm signal capture */
signal(SIGINT,exit_func);
while (1)
{
//printf("Dd");
}
}
Do not raise SIGSTOP, call exit_func directly.
include the appropriate headers:
#include <stdlib.h> //exit
#include <string.h> //strerror
also, why do you try to set up a signal handler in your exit function? it doesn't make sense.

Resources