How to interrupt sleep() without using multiple threads in C? - c

I'm writing a terminal application for Linux which uses the ncurses library to update the terminal with a 1 second sleep in between each update. I want to keep this sleeping behaviour, but at the same time I want the program to exit immediately when I hit the q-key, not getting a potential 1 second lag. Therefore I need a way to interrupt sleep(). I am aware that alarm() will do that for me, but for that I need another thread which calls alarm(). This does not mix well with ncurses which is single-threaded. Is there anything that might help me achieve this?
My code is something like this:
void run() {
while (1) {
for (int i = 0; i < num_things; ++i) {
if (getch() == 'q') return;
printw("Something");
refresh();
}
sleep(1);
}
}

Thanks to #Barmar. Use ncurses timeout(1000) before getch(). Like this:
void run() {
while (1) {
for (int i = 0; i < num_things; ++i) {
printw("Something");
refresh();
}
timeout(1000);
if (getch() == 'q') return;
}
}

Related

How to handle Control-C signal while designing a shell?

I am trying to implement some of the features present in the shell including quitting only when a user enters quit and not on Ctrl+C. Below is a simplified version of the code that I am tried.
Code 1: without calling loop() in a signal handler.
void loop(){
while(1){
char a[20];
printf("Enter Command : " );
scanf("%s",a);
printf("%s\n", a);
}
}
void sigintHandler(int sig_num)
{
signal(SIGINT, sigintHandler);
printf("\n");
}
int main(int argc, char const *argv[]) {
signal(SIGINT, sigintHandler);
loop();
return 0;
}
The output of Code 1:
As can be seen on a third input, I go to a new line and continued right from where I left the loop. I want to instead start the loop again. So, I did the following modification by calling loop in signal handler itself.
void loop(){
while(1){
char a[20];
printf("Enter Command : " );
scanf("%s",a);
printf("%s\n", a);
}
}
void sigintHandler(int sig_num)
{
signal(SIGINT, sigintHandler);
printf("\n");
loop();
}
int main(int argc, char const *argv[]) {
signal(SIGINT, sigintHandler);
loop();
return 0;
}
Output for code 2:
As can be seen that when I clicked first-time Ctrl+C (on input line 3), it works properly and I can continue. But when I click Ctrl+C second time I don't go to a new line and I have to press enter for a program to execute.
I went through this question but it doesn't seem to apply for my case. This is my first time using signals and system calls so my question may come as silly. But it will be a great help if someone can help me to get to a proper way of implementing signals. Thank you.
Jonathan Leffler provided helpful hints (though not sufficient, at least on some popular operating system):
Look at what scanf() returns.
Don't use loop() in the signal handler
Don't use signal() — use sigaction(). In your case, this has two advantages:
Restoring the signal action to the default state on call of the signal handler can be avoided, so you don't have to change the action again in the handler.
Restarting the read() system call (inside scanf()) can be avoided, so that scanf() returns and you can react to the interrupt in the first place.
So, the signal handler can be just
void sigintHandler(int sig_num)
{
printf("\n"); // or perhaps better write(1, "\n", 1)
}
The signal(SIGINT, sigintHandler); in main() can be replaced with
sigaction(SIGINT, &(struct sigaction){ .sa_handler = sigintHandler }, NULL);
and the scanf("%s",a); with
if (scanf("%s", a) == EOF)
{
if (errno == EINTR) continue; // read operation interrupted by signal
return;
}
EOF is returned on interrupt as well as on end of file, so the cases are to be distinguished through errno. Besides, it's nice if your program provides a way to exit it, thus the return.

Raspberry Pi clean exit on CTRL+C in C

First of all, let me apologize as I can see that similar questions have been posted quite a few times in the past. However, as I am very unfamiliar with C, I need help confirming this.
I am trying to ensure that my program leaves a clean gpio if I interrupt it with CTRL+C. Easily done in python or java, but C proves to be a harder nut to crack for me, as I was led to believe that no try-catch-finally exists in C. Googling it, I found what I think may be the solution, but unexperienced as I am, I'm not sure it's done properly. Here is my code:
#include <stdio.h>
#include <wiringPi.h>
#include <signal.h>
void CleanGPIO() {
pinMode(1,INPUT);
}
int main()
{
wiringPiSetup();
signal(SIGINT, CleanGPIO);
pinMode(1, PWM_OUTPUT);
for (int i = 0; i < 1024; ++i) {
pwmWrite(1, i);
delay(1);
}
for (int i = 1023; i >= 0; --i) {
pwmWrite(1, i);
delay(1);
}
pinMode(1,INPUT);
return 0;
}
I have tested it and it works as intended (pin 1 is set as IN after I interrupt it with CTRL+C), but I'm concerned if this is the safe way to do it, and if there is a better solution available.
calling any function which is not speficied as signal-safe from a signal handler is undefined behaviour. I suppose there is no such guarantee about pinMode.
The proper way would be to set a volatile int flag that you periodically check in your main loop.
volatile int terminating = 0;
void terminate(int sign) {
signal(SIGINT, SIG_DFL);
terminating = 1;
}
int main() {
for (...) {
if (terminating) {
// cleanup
exit(1);
}
}
}
the call to signal inside the handler is to allow force terminating the program with a second ctrl+c in case proper clenup takes too long or is stuck for any reason.
Your solution is nearly right. You should also call exit in order to force the program to terminate (assuming you want to terminate immediately). The exit call takes a parameter which is the exit status to return to the caller (e.g., the shell). This should be non-zero for abnormal termination.
So, it should be:
void CleanGPIO() {
pinMode(1,INPUT);
exit(1);
}
If you don't want to exit from the handler but from main in a more controlled fashion you can set a flag instead and check the flag value inside the loops.

How to stop a running pthread thread?

How can I exit or stop a thread immediately?
How can I make it stop immediately when the user enters an answer?
I want it to reset for every question.
Here's my code where threading is involved
int q1() {
int timer_start;
char ans[] = "lol";
char user_ans[50];
timer_start = pthread_create( &xtimer,NULL,(void*)timer_func,(void*)NULL);
printf("What is the capital city of Peru?\n");
while(limit){
scanf("%s",user_ans);
if(limit)
{
if(!strcmp(user_ans, ans))
{
// printf("YAY!\n");
score++;
// q2();
}
else
{
game_over();
}
}
}
}
You can simply call pthread_cancel on that thread to exit it. And you can send SIGSTOP/SIGCONT signal via pthread_kill to stop/restart it.
But if all you want is a timer, why must you thread?
Based on your code I can give a simple answer:
In this case do not use threads at all.
You do not need them. Store the start time, let the user answer, check the time again after user gives an answer.
{
time_t startTimeSec = time(NULL);
// answering
time_t endTimeSec = time(NULL);
time_t timeTakenSec = endTime-startTime;
if (timeTaken > 10) {
// do your thing
}
}
To answer your question:
You should use a mutex-protected or volatile variable to asynchronously communicate between threads. Set that variable from one thread and check it in another. Then reset its value and repeat. A simple snippet:
int stopIssued = 0;
pthread_mutex_t stopMutex;
int getStopIssued(void) {
int ret = 0;
pthread_mutex_lock(&stopMutex);
ret = stopIssued;
pthread_mutex_unlock(&stopMutex);
return ret;
}
void setStopIssued(int val) {
pthread_mutex_lock(&stopMutex);
stopIssued = val;
pthread_mutex_unlock(&stopMutex);
}
Using pthread_cancel() is an option, but I would not suggest doing it. You will have to check the threads state after this call returns, since pthread_cancel() does not wait for the actual thread stop. And, which to me is even more important, I consider using it ugly.
Using methods to stop a thread is a brute way.
You should rather politely ask the thread to stop by signalling.
Thereby the thread will have an option to tidy after itself e.g. if it has allocated memory, which it will not have any opportunity to do if the thread is cancelled.
The method is relatively simple and comprises no OS signalling:
define a thread state variable or structure outside the thread. Point to it at the pthread_create and dereference the state variable in the thread.
int thread_state = 0; // 0: normal, -1: stop thread, 1: do something
static void *thread_1 (void *arg)
{
int* pthread_state = arg;
... // initialize the thread locals
while(1)
{
switch( *pthread_state )
{
case 0: // normal thread loop
...
break;
case -1:
... // tidy or whatever is necessary
pthread_exit(0); // exit the thread signalling normal return
break;
case 1: //
... // do something special
break;
}
}
}
pthread_create (&t_1, NULL, thread_1, (void*)&thread_state);
...
thread_state = -1; // signal to the thread to stop
// maybe use pthread_exit(0) to exit main.
// this will leave the threads running until they have finished tidy etc.
It is even possible to communicate with the thread using a structure provided that it is simple 'atomic' variables or a simple handshake mechanism is established. Otherwise it may be necessary to use mutex.
Use pthread_join to wait for threads to terminate.
#Naruil's suggestion to call pthread_cancel() is pretty much the best solution i found, but it won't work if you didn't do the following things.
According to the man-page of pthread_cancel the pthread_cancelibility depend on two thing
thread_cancel_state.
thread_cancel_type.
thread_cancel_state is PTHREAD_CANCEL_ENABLE by default, so our main concern is about the thread_cancel_type, it's default value is type PTHREAD_CANCEL_DEFFERED but we need PTHREAD_CANCEL_ASYNCHRONOUS to set on that thread, which we wan't to cancel.
Following an example given::
#include <stdio.h>
#include <pthread.h>
void *thread_runner(void* arg)
{
//catch the pthread_object as argument
pthread_t obj = *((pthread_t*)arg);
//ENABLING THE CANCEL FUNCTIONALITY
int prevType;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &prevType);
int i=0;
for( ; i < 11 ; i++)//1 - > 10
{
if(i == 5)
pthread_cancel(obj);
else
printf("count -- %d", i);
}
printf("done");
}
int main(int argc, char *argv[])
{
pthread_t obj;
pthread_create(&obj, NULL, thread_runner, (void*)&obj);
pthread_join(obj, NULL);
return 0;
}
run it using gcc filename.c -lpthread and output the following::
count -- 0
count -- 1
count -- 2
count -- 3
count -- 4
note that the done is never printed because the thread was canceled when the i became 5 & the running thread was canceled. Special thanks #Naruil for the "pthread_cancel" suggestion.

Does sleep() interfere with scanf()?

I have two threads
xThread : Continuously Prints X on the console
inputThread: Gets input from the stdin
The continuous printing stops when the user enters 'C' or 'c'
#include<stdio.h>
#include<sys/select.h>
#include<pthread.h>
#define S sleep(0)
int read_c = 0;
pthread_mutex_t read_c_mutex = PTHREAD_MUTEX_INITIALIZER;
void* inputThread_fn(void* arg)
{
char inputChar;
while(1)
{
S;
printf("\nChecking input");
scanf("%c",&inputChar);
if(inputChar=='C' || inputChar == 'c')
{
pthread_mutex_trylock(&read_c_mutex); /*<--This must be _lock ?
because with the use of trylock even If i don't aquire a lock I go ahead and modify
the variable?*/
read_c = 1;
pthread_mutex_unlock(&read_c_mutex);
pthread_exit(NULL);
}
}
}
void* xThread_fn(void* arg)
{
while(1)
{
S;
pthread_mutex_trylock(&read_c_mutex);
if(!read_c)
printf(" X");
else
pthread_exit(NULL);
pthread_mutex_unlock(&read_c_mutex);
}
}
void* yThread_fn(void* arg)
{
while(1)
{
S;
pthread_mutex_trylock(&read_c_mutex);
if(!read_c)
printf(" Y");
else
pthread_exit(NULL);
pthread_mutex_unlock(&read_c_mutex);
}
}
int main()
{
pthread_t xThread,yThread,inputThread;
pthread_create(&xThread,NULL,xThread_fn,NULL);
pthread_create(&inputThread,NULL,inputThread_fn,NULL);
pthread_join(xThread,NULL);
pthread_join(inputThread,NULL);
return 0;
}
When I use sleep(1) the threads are spawned and [irrespective of which thread is started first] when the program reaches scanf in inputThread it halts for the user input and the code does not proceed until I enter an input.
When I execute the code with sleep(0), scanf does not halt for the input, it keeps printing 'X' until I enter 'C' or 'c'
Does sleep() interfere with scanf in someway?
Note: I am aware of select being used for non-blocking input. I have tried the same too and the code runs fine. I just want to know in the above case why inconsistent behaviour arises?
Update (Using trylock)
void* inputThread_fn(void* arg)
{
char inputChar;
while(1)
{
S;
scanf("%c",&inputChar);
if(inputChar=='C' || inputChar == 'c')
{
pthread_mutex_trylock(&read_c_mutex);
read_c = 1;
pthread_mutex_unlock(&read_c_mutex);
pthread_exit(NULL);
}
}
}
void* xThread_fn(void* arg)
{
while(1)
{
S;
pthread_mutex_trylock(&read_c_mutex);
if(!read_c)
{
pthread_mutex_unlock(&read_c_mutex);
printf(" X");
}
else
{
pthread_mutex_unlock(&read_c_mutex);
pthread_exit(NULL);
}
fflush(stdout);
}
}
void* yThread_fn(void* arg)
{
while(1)
{
S;
pthread_mutex_trylock(&read_c_mutex);
if(!read_c)
{
pthread_mutex_unlock(&read_c_mutex);
printf(" Z");
fflush(stdout);
}
else
{
pthread_mutex_unlock(&read_c_mutex);
pthread_exit(NULL);
}
}
}
The reason you don't see output is because you're not flushing the buffer.
The reason you don't need to flush the buffer with sleep(0) is because the writer thread writes so much data that the buffer fills up and is automatically flushed.
#define SLEEP_TIME 1
void* xThread_fn(void* arg)
{
while (1) {
sleep(SLEEP_TIME);
pthread_mutex_lock(&read_c_mutex);
if (read_c) {
pthread_mutex_unlock(&read_c_mutex);
return NULL;
}
pthread_mutex_unlock(&read_c_mutex);
printf(" X");
fflush(stdout); // <-- necessary
}
}
Don't use pthread_mutex_trylock()
Don't use pthread_mutex_trylock() here. It's wrong.
The difference between lock() and trylock() is that lock() will always succeed1 but trylock() will sometimes fail. That's why it's called "try".
Since trylock() sometimes fails, you have to handle the case where it failed. Your code doesn't handle the case: it simply plows forward, pretending it acquired the lock. So, suppose trylock() doesn't lock the mutex. What happens?
pthread_mutex_trylock(&read_c_mutex); // Might fail (i.e., not lock the mutex)
read_c = 1; // Modifying shared state (Wrong!)
pthread_mutex_unlock(&read_c_mutex); // Unlocking a mutex (Wrong!)
Then there's the question of how the code should handle trylock() failing. If you can't answer this question, then the default answer is "use lock()".
In the reader thread, you can't use trylock() because you have to lock the mutex:
int r = pthread_mutex_trylock(&read_c_mutex);
if (r != 0) {
// Uh... what are we supposed to do here? Try again?
} else {
read_c = 1;
pthread_mutex_unlock(&read_c_mutex);
}
In the writer thread, there's no point in using trylock():
int r = pthread_mutex_trylock(&read_c_mutex);
if (r != 0) {
// Okay, just try again next loop...
} else {
if (read_c) {
pthread_mutex_unlock(&read_c_mutex);
pthread_exit(NULL);
} else {
pthread_mutex_unlock(&read_c_mutex);
}
}
However, this is entirely pointless. The only reason trylock() will fail in the writer thread is if the reader thread owns the lock, which only happens if it is currently in the process of setting read_c = 1;. So you might as well wait for it to finish, since you know you're going to exit anyway (why write more output after you know that the user has signaled your program to stop?)
Just use lock(). You'll use lock() 99% of the time, and trylock() is for the other 1%.
1: The lock() function can fail, but this usually means you've misused the mutex.
Misconceptions about lock() and trylock()
You said this about trylock():
If i have another thread accessing the variable read_input then will it be appropriate to use it?
I think there is a very fundamental misunderstanding here about the nature of mutexes. If another thread weren't accessing the variable at the same time, then you wouldn't need a mutex at all.
Suppose you're doing important work at the office, and you need to use the photocopier. Only one person can use the photocopier at a time. You go to the photocopier and someone's already using it.
If you wait in line until it's your turn, then that's lock().
If you give up and go back to your desk, then that's trylock(). (Your program actually ignores the return code for trylock(), so you basically start mashing buttons on the photocopier even if someone else is using it.)
Now imagine that it takes one minute to use the photocopier, only two people ever use the photocopier, and they only use the photocopier once every twenty years.
If you use lock(), then you wait in line for at most one minute before using the photocopier.
If you use trylock(), then you give up and go back to your desk and wait twenty years before trying the photocopier again.
It doesn't make any sense to use trylock(), does it? Are your threads so impatient that they can't spend even one minute in line once every twenty years?
Now your boss comes down and said, "Where is that report I asked you to photocopy?" And you say, "Well, I went to the photocopier six years ago but someone was using it."
The numbers (one minute every twenty years) are based on Latency Numbers Every Programmer Should Know, where it notes that locking/unlocking a mutex is about 25ns. So if we pretend that it takes one minute to lock and then unlock a mutex, then sleep(1) causes the thread to wait for twenty years.

How to call function with infinite-loop?

I need help to clear my concepts.
I have a function which toggle the Led status on/off after every second. Now the code for the on/off runs inside infite loop.
Example:
void ToggleLed( int pin_number)
{
// some code
while(1)
{
// code to execute the Led status
}
}
Now when I integrate this code with base line and called that function inside other function it just doesnt work no other functionality of software works.
Question: Function has infinite-loop and that it doesn't come out of control and other functions called after that function doesn't work.
If that is the case do I need to provide separate thread to it?
Any suggestion will be helpful.
Yes you will need a separate thread, or some other form of asynchronous execution. Once you enter that while loop, no other code runs in that thread. Ever.
If I understand correcctly nothing works in your integrated version. In that case, yes you probably need to run the infinite loop on a separate thread, because your function with the infinit loop will never exit, so no other code will ever run on that thread.
You don't say what OS, but yes, set it as a low-priority thread, minimal stack size. I flash a LED in my projects, just so I can easily see if the code has reached the abort-handler yet :)
void LEDflash_task_code(void *p)
{
while (1)
{
FIO1CLR=STATUS_LED;
OSsleep(750);
FIO1SET=STATUS_LED;
OSsleep(250);
};
};
If you have access to hardware peripheral timers (any micrcontroller/microprocessor application), you should use those hardware timers, not threads nor software sleep().
void init_toggle_led (uint32_t interval)
{
setup_hardware_timer(interval);
}
void toggle_led (void)
{
if( (hardware_timer_register & flag) > 0 )
{
port = port ^ pin_mask;
}
}
main()
{
init_toggle_led(1000);
for(;;)
{
do_stuff();
toggle_led();
}
}
This was an example with polling. Alternatively, you can use hardware interrupts from the timers and toggle the port from there.
As David mentioned, you should run your LED code in a separate thread. http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html#BASICS
Once you have threads, if you want your code to be able to stop your LED from blinking, then add a flag that's checked inside the while loop at each iteration, and if it's set then break out.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void * toggle_led(void *ptr);
int stop=0;
int main (int argc, const char * argv[])
{
printf("Hello, World!\n");
// set up thread
pthread_t LED_thread;
char * message = "blink!";
pthread_create( &LED_thread, NULL, toggle_led, (void*) message);
// do some other work
sleep(5);
// ok you want to quit now
stop=1;
pthread_join(LED_thread, NULL);
printf("Goodbye!\n");
return 0;
}
void *toggle_led(void *ptr)
{
while (!stop)
{
printf("%s \n", (char *)ptr);
sleep(1);
}
}
I think you need to implement as a watchdog functionality. Because if you use threads then even if other threads has some issues(like deadlock), your LEDs will toggle as long as toggle_led thread works. You need to implement an toggle_led() function and call from each of other threads /functions before returning to make sure all other threads/functions are getting executed successfully without waiting continuously for some resources

Resources