My code is as follows,The first time ,alarm works very well and handler2() function can work. however, the alarm doesn't work after it implement "doMain()" in the "handler2()".
I mean after the second time print ""In main Pleasae input: \n"", handler2() doesn't wrok anymore.
I don't know why? My code as follows:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#define MAX_LEN_COMM 64
jmp_buf jumper;
int stop =0; //o is not stop ,otherwise is stop;
void hanlder2();
void doMain();
void handler2()
{
int len_command = 0;
char character;
char commandStr[60];
printf("******************************\n");
printf("In Alarm Pleasae input: \n");
while((character=getchar())!='\n')
{
commandStr[len_command]=character;
len_command++;
}
commandStr[len_command]='\0';
printf("In Alarm input is %s\n",commandStr);
if (strcmp(commandStr,"N")==0||strcmp(commandStr,"n")==0){
printf("In Alarm You put no, we will stop alarm \n");
stop=1;
longjmp(jumper, 2);
}
else if(strcmp(commandStr,"Y")==0||strcmp(commandStr,"y")==0){
printf("In Alarm You put yes, we will continue alarm \n");
signal(SIGALRM, handler2);
alarm(5);
doMain();
}
}
void doMain(){
while(1){
setjmp(jumper);
if(stop==0){
signal(SIGALRM, handler2);
printf("return time %d\n",alarm(5));
}
int len_command = 0;
char character;
char commandStr[60];
printf("In main Pleasae input: \n");
while((character=getchar())!='\n')
{
commandStr[len_command]=character;
len_command++;
}
commandStr[len_command]='\0';
printf("In main input is %s\n",commandStr);
if (strcmp(commandStr,"N")==0||strcmp(commandStr,"n")==0){
printf("In main You put no\n");
}
else if(strcmp(commandStr,"Y")==0||strcmp(commandStr,"y")==0){
printf("In main You put yes\n");
}
}
}
void main()
{
doMain();
}
What you are doing is very wrong.
First, the signature of the handler should be void handler(int sig).
Second, there are very few functions that are safe to use within a handler so you should try to get out of a handler as quickly as possible and definitely not doing console i/o. You are using several unsafe library functions.
Lastly a signal handler is a function. It runs and returns to where your program was interrupted by the signal. During the time a handler runs signals of the same type are not deliverd. By calling doMain() from the handler - which is crazy - the handler never ends. Because it doesn't end you won't see any more alarm signals.
Related
Problem
I wish to be able to pause the execution of a thread from a different thread. Note the thread paused should not have to cooperate. The pausing of the target thread does not have to occur as soon as the pauser thread wants to pause. Delaying the pausing is allowed.
I cannot seem to find any information on this, as all searches yielded me results that use condition variables...
Ideas
use the scheduler and kernel syscalls to stop the thread from being scheduled again
use debugger syscalls to stop the target thread
OS-agnostic is preferable, but not a requirement. This likely will be very OS-dependent, as messing with scheduling and threads is a pretty low-level operation.
On a Unix-like OS, there's pthread_kill() which delivers a signal to a specified thread. You can arrange for that signal to have a handler which waits until told in some manner to resume.
Here's a simple example, where the "pause" just sleeps for a fixed time before resuming. Try on godbolt.
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
void safe_print(const char *s) {
int saved_errno = errno;
if (write(1, s, strlen(s)) < 0) {
exit(1);
}
errno = saved_errno;
}
void sleep_msec(int msec) {
struct timespec t = {
.tv_sec = msec / 1000,
.tv_nsec = (msec % 1000) * 1000 * 1000
};
nanosleep(&t, NULL);
}
void *work(void *unused) {
(void) unused;
for (;;) {
safe_print("I am running!\n");
sleep_msec(100);
}
return NULL;
}
void handler(int sig) {
(void) sig;
safe_print("I am stopped.\n");
sleep_msec(500);
}
int main(void) {
pthread_t thr;
pthread_create(&thr, NULL, work, NULL);
sigset_t empty;
sigemptyset(&empty);
struct sigaction sa = {
.sa_handler = handler,
.sa_flags = 0,
};
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, NULL);
for (int i = 0; i < 5; i++) {
sleep_msec(1000);
pthread_kill(thr, SIGUSR1);
}
pthread_cancel(thr);
pthread_join(thr, NULL);
return 0;
}
Look at this Unix C program:
#include <stdio.h>
#include <signal.h>
void handler(int signum)
{
printf("Handler signum=%d\n",signum);
}
int main(int argc, char *argv)
{
printf("Start\n");
signal(SIGFPE, handler);
int i=10/0;
printf("Next\n");
return 0;
}
As you can see, i am connecting SIGFPE to an handler.
Then, i make a DIV0 erreur.
The handler is fired, that is great.
But, this handler is called in loop !
Why ?
Thanks
If you simply return from your handler, execution resumes at the point where the signal was thrown, which results in another divide by zero error, which results in the handler being called again, and so on. You need to arrange for execution to continue at some other point in the code. The traditional approach is to use setjmp/longjmp, something like this
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
jmp_buf buf;
void handler(int signum)
{
longjmp(buf, signum);
}
int main(int argc, char *argv)
{
int rc = setjmp(buf);
if (rc == 0) {
printf("Start\n");
signal(SIGFPE, handler);
int i=10/0;
}
printf("Handler signum=%d\n", rc);
printf("Next\n");
return 0;
}
Note: this approach is very old school, and probably someone can suggest a better way to handle it. Also, you are probably better off calling sigaction rather than signal, as the semantics of signal are not consistent across different versions of Unix.
I have started working on POSIX threads. I wrote a simple code.
My question is on Mutex.
Initializing the mutex inside threaded function gives wrong result. While initializing the mutex inside main function (before creation of threads) gives proper result. Why is that happening?
The count value is expected to be 200000 but it is showing some improper value < 200000.
Here is my code.
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <malloc.h>
void *thread_handler (void *name);
unsigned long int count=0;
pthread_mutex_t lock;
void main () {
pthread_t thread_num[2];
pthread_attr_t attr;
pthread_attr_init (&attr);
int i;
for (i=0;i<2;i++) {
if (pthread_create (&thread_num[i],&attr,(void *) thread_handler,NULL)<0) {
printf ("\n Error in Creating the Threads");
}
}
for (i=0;i<2;i++) {
pthread_join(thread_num[i],NULL); //Waiting for the Thread to Exit
}
printf ("\n The value of count=%ld\n",count);
}
void *thread_handler (void *arg) {
int i;
if (pthread_mutex_init (&lock,NULL)!=0) {
printf ("\n Error in Initializing the Mutex");
}
pthread_mutex_lock (&lock);
for (i=0;i<100000;i++) {
count++;
}
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
Thanks in Advance,
NDPrasad.
When you initialize the mutex inside the thread_handler function, it is initialized twice(because you create two threads that execute this function). It causes undefined behavior(which means that anything can happen).
A quote from here:
Attempting to initialize an already initialized mutex results in undefined behavior.
I run my game on linux system of TV, when I exit game, the system will crash.
from the output log, I know my game has been quite, but system crash following.
the main function like below:
int main(int argc, char** argv)
{
......
SDL_Quit();
printf("Log: exit end. \n);// it's printed on console
return 0;
}
I can find the output log about Log: exit end. So the game has been exit right?
I found the game exit will only crash after create threads.
Here is the run function in thread below:
while ( pThread->m_running )
{
string str;
string cmdStr;
if ( pThread->GetSendMsg(str, cmdStr) )
{
string returnStr = Connection::DealHttpSendMsg( str, cmdStr );
pThread->AddReturnMsg( returnStr );
haveData = true;
}
else
{
SDL_Delay(100);
haveData = false;
}
}
My question is that if the m_running is alway true. so when I exit the game, the thread is still running. Will it cause the crash?
It will if that thread tries to access resources that are being simultaneously destroyed by the main thread.
Just quitting the app won't crash it if you have a worker thread that does nothing.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void* run_me(void*)
{
while (1)
{
printf("Sleeping..\n");
sleep(1);
}
}
int main()
{
pthread_t my_thread;
pthread_create(&my_thread, NULL, &run_me, NULL);
sleep(2);
return 0;
}
return 0; terminates only the main thread. Try to use exit(0) instead.
I am working in the Linux environment, and I have a C++ program, what I want is when I cancel the program with ctrl+c I would like that the program executes a function, to close some files and print some sutff, is there any way to do this?. Thank you.
signal() can be dangerous on some OSes and is deprecated on Linux in favor of sigaction(). "signal versus sigaction"
Here's an example that I ran across recently ("Tap the interrupt signal") and modified as I was playing around with it.
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<string.h>
struct sigaction old_action;
void sigint_handler(int sig_no)
{
printf("CTRL-C pressed\n");
sigaction(SIGINT, &old_action, NULL);
kill(0, SIGINT);
}
int main()
{
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_handler = &sigint_handler;
sigaction(SIGINT, &action, &old_action);
pause();
return 0;
}
For a full working example you can try the following code:
#include <signal.h>
#include <stdio.h>
#include <stdbool.h>
volatile bool STOP = false;
void sigint_handler(int sig);
int main() {
signal(SIGINT, sigint_handler);
while(true) {
if (STOP) {
break;
}
}
return 0;
}
void sigint_handler(int sig) {
printf("\nCTRL-C detected\n");
STOP = true;
}
Example run:
[user#host]$ ./a.out
^C
CTRL-C detected
You have to catch the SIGINT. Something like this:
void sigint_handler(int sig)
{
[do some cleanup]
signal(SIGINT, SIG_DFL);
kill(getpid(), SIGINT);
}
loads more detail here
Short answer: look into the signal function, specifically catching SIGINT. You write a callback function and pass it to the system via the signal function, then when that particular signal happens, the system calls your callback function. You can close files and do whatever other cleanup stuff you want in there.
Note to people who might stumble upon this question, looking for the answer in Windows instead:
Use the SetConsoleCtrlHandler API call to set a custom handler and watch for CTRL_C_EVENT, CTRL_BREAK_EVENT or CTRL_CLOSE_EVENT.