thread cancel issue - c

I am facing one issue related to pthread_cancel. Please see the code below:
void* func(void *arg)
{
while(1)
{
sleep(2);
}
}
#include<stdlib.h>
#include <stdio.h>
#include <pthread.h>
int main()
{
void *status;
pthread_t thr_Var;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
pthread_create(&thr_Var,NULL,func,NULL);
pthread_cancel(thr_Var);
pthread_join(thr_Var,&status);
return 0;
}
My doubt is even if i disable the cancel state, still pthread_cancel is working and thread is getting terminated.
Any help will be appreciated

pthread_setcancelstate sets the cancelability type of the calling thread, i.e. the main thread in your case. So if you want to make the newly created thread non-cancelable you should call that function from within the context of that thread.
See man 3 pthread_setcancelstate
Note that while Linux pthreads implementation permits a NULL oldstate pointer, POSIX, however, does not specify that, so it's best to provide a pointer for oldsate.

Related

unknown failure when pthread_cancel right after pthread_create and pthread_detach

I've tested the thread cancellation process, and have a code like this.
It works on my ARM machine, and sometimes works fine, sometimes leads to a segfault, sometimes stuck after created.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
void *t(void *ptr)
{
printf("in t\n");
sleep(0.3);
return NULL;
}
int main() {
pthread_t p;
pthread_create(&p, NULL, t, NULL);
printf("created\n");
pthread_detach(p);
pthread_cancel(p);
printf("canceled\n");
return 0;
}
have no idea which part is leading to the issue(stuck/segfault).
I answered this same question 18 years ago. It is not safe to call pthread_cancel on a detached thread.
Your code has a race condition so its behavior is undefined. If the thread manages to terminate before you call pthread_cancel, you are passing an invalid parameter to pthread_cancel and that is undefined behavior.
If the code in main is managing the lifetime of the thread, do not detach it because otherwise there is no way to ensure the thread ID remains valid. If the code in main is not managing the lifetime of the thread, do not call pthread_cancel in it. You will never find a safe way to split the difference.
You should think of pthread_detach as rendering the thread ID invalid (or "semantically closed" as Glenn Burkhardt put it) and not use it again.
As Some programmer dude points out, your sleep rounds to zero which makes the race condition more likely to encounter.

Ending terminal application on mac + cleanup process

I am trying to create a c program which has an infinite loop in the main method (multi-threaded application). We are using pthreads and POSIX shared memory between two applications. If I exit one of the programs using the command line (CTL+C), then I want to run a cleanup method to cleanup all allocated memory and removed the POSIX shared memory map.
int main () {
for (;;)
{
}
destroy_shared_object(shm, MEM_MAP_SIZE);
exit(EXIT_SUCCESS);
return 0;
}
Right now this is what I have above, however when I exit the program I don't think it removes the shared memory map and cleans up. Any help would be appreciated!
You may catch CTRL+C with a signal() handler and set a flag variable within the signal handler:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
static volatile sig_atomic_t running = 1;
void sighandler(int signum) {
running = 0;
}
int main() {
signal(SIGINT, sighandler);
while(running) {
sleep(1);
}
printf("Do the cleanup...\n");
return 0;
}
EDIT:
It's probably better to use sigaction() instead:
WARNING: the behavior of signal() varies across UNIX versions,
and has also varied historically across different versions of
Linux. Avoid its use: use sigaction(2) instead. See > Portability
below.

C linux signals and functions

I got this issue, which I will simplify below:
#include <stdio.h>
#include <signal.h>
int main(void) {
signal(SIGALRM, &INThandler);
//get menu options which Im not going to put here
game(...stuff...);
}
void game(..stuff...) {
//do the game stuff AND set an alarm()
}
void INThandler(int sig) {
system("clear");
printf("Time is up!\n");
//I WANT game() TO STOP WHICH WILL EXIT TO MAIN WHERE MORE STUFF IS HAPPENING
}
In game() I have
while(counter <= amount)
So I wanted to pass the variables counter and amount into INThandler so I could change them so the condition is false, however INThandler is only called when the alarm is at 0 and is not called with parameters. game() continues and I don't want it to. If there is a better way please tell me.
Use global variables for counter and amount ?
When a function is called and that function has variables in it, those variables are allocated on the stack. If you define a global variable, it will be instead be allocated as the program loads. Your signal handler should have access to those variables.
#include <stdio.h>
#include <signal.h>
#include <stdlib.h> //Also include this, needed for exit(returncode)
int counter; //Not inside any function
int amount; //All functions may access these
int main(void) {
signal(SIGALRM, &INThandler);
//get menu options which Im not going to put here
game(...stuff...);
}
void game(..stuff...) {
//do the game stuff AND set an alarm()
}
void INThandler(int sig) {
//Do stuff with counter and amount
//system("clear"); I recommend that you do not use system to clear the screen, system(command) is inefficient.
printf("\033[H\033[JTime is up!\n");
//Do that extra stuff you want to do in main here, then
exit(0);
}
Another note: according to signal(2) in the Linux programming manual:
The only portable use of signal() is to set a signal's disposition to
SIG_DFL or SIG_IGN. The semantics when using signal() to establish a
signal handler vary across systems (and POSIX.1 explicitly permits
this variation); do not use it for this purpose.
POSIX.1 solved the portability mess by specifying sigaction(2), which
provides explicit control of the semantics when a signal handler is
invoked; use that interface instead of signal().
To register a signal handler using sigaction,
#include <signal.h>
int main(){
const struct sigaction saSIGALRM = {
.sa_handler = mySignalHandler, //replace this with your signal handler, it takes the same parameters as using signal()
};
sigaction(SIGALRM, &saSIGALRM, 0);
}
It's simpler than it looks. Remember, computers are slow today because of inefficient programming. Please, please, please, for efficient programs, use this instead.
Click here for more cool things sigaction can do, along with why not to use signal()

CLONE_VM flag makes itimer inaccurate?

Recently I come across a problem about sharing memory with multiprocess. Consider the code below, the main purpose is to let child process alarmed by the itimer's signal handler, do some output. But what confuses me is that when I set the CLONE_VM flag in clone() function, the itimer may go wrong, and the output text will stuff your console.
What I expect is : print "---Alarm!\n---ChildThread is awaked.\n---foo=10" every second.
The actual situation is : repeat printing the text above very fast.
I'd like to know how to spawn a child PROCESS and let it share its parent's memory in the meanwhile. Thanks a lot.
#define _GNU_SOURCE
#include <stdio.h>
#include <signal.h>
#include <sched.h>
#include <stdlib.h>
#include <linux/sched.h>
#include <sys/time.h>
static volatile int foo = 100;
int pidChild;
void AlarmThread(int sig)
{
printf("---Alarm!\n");
kill(pidChild, SIGCONT);
}
int ChildThread(void *arg)
{
raise(SIGSTOP);
while(1)
{
printf("---ChildThread is awaked.\n");
printf("---foo=%d\n", foo); // If CLONE_VM is set, this variable may be changed by main thread.
raise(SIGSTOP);
}
return 0;
}
int main(int argc, char **argv)
{
void *stack = malloc(4000) + 4000;
struct itimerval itimer;
signal(SIGALRM, AlarmThread);
pidChild = clone(ChildThread, stack, CLONE_VM | CLONE_SIGHAND, NULL);
itimer.it_interval.tv_sec = 1;
itimer.it_interval.tv_usec = 0;
itimer.it_value = itimer.it_interval;
setitimer(ITIMER_REAL, &itimer, NULL); // Set up a 1 tick-per-sec timer.
foo = 10; // Test if the child thread shares the main thread's memory.
while(1);
return 0;
}
I would really caution you against doing this. Sharing memory does not mean only application memory, but also library memory (the standard library and any third-party libraries you may use), and they may not be prepared for having other processes clobber their internal data structures, especially when they believe themselves to be running single-threaded.
If you just want a process in order to have a killable PID for a thread as part of the publicly visible interface of your application, why not make the actual code run in a thread, and spawn a useless child process that does nothing but for(;;)pause();? Then, have the thread respond to the death of this child process by exiting.
But what confuses me is that when I set the CLONE_VM flag in clone()
function, the itimer may go wrong, and the output text will stuff your
console.
What does "may go wrong" mean? What happened? What did you expect? You need to be clear when asking questions.
CLONE_VM has almost nothing to do with itimer. The fact that you are using advanced syscalls like this without even being able to formulate what you are trying to do and why leads me to believe this is a school assignment.

Signal handler for SIGALRM does not work even if resetting in the handler

The example code of section 10.6, the expected result is:
after several iterations, the static structure used by getpwnam will be corrupted, and the program will terminate with SIGSEGV signal.
But on my platform, Fedora 11, gcc (GCC) 4.4.0, the result is
[Langzi#Freedom apue]$ ./corrupt
in sig_alarm
I can see the output from sig_alarm only once, and the program seems hung up for some reason, but it does exist, and still running.
But when I try to use gdb to run the program, it seems OK, I will see the output from sig_alarm at regular intervals.
And from my manual, it said the signal handler will be set to SIG_DEF after the signal is handled, and system will not block the signal. So at the beginning of my signal handler I reset the signal handler.
Maybe I should use sigaction instead, but I only want to know the reason about the difference between normal running and gdb running.
Any advice and help will be appreciated.
following is my code:
#include "apue.h"
#include <pwd.h>
void sig_alarm(int signo);
int main()
{
struct passwd *pwdptr;
signal(SIGALRM, sig_alarm);
alarm(1);
for(;;) {
if ((pwdptr = getpwnam("Zhijin")) == NULL)
err_sys("getpwnam error");
if (strcmp("Zhijin", pwdptr->pw_name) != 0) {
printf("data corrupted, pw_name: %s\n", pwdptr->pw_name);
}
}
}
void sig_alarm(int signo)
{
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
err_sys("getpwnam error");
alarm(1);
}
According to the standard, you're really not allowed to do much in a signal handler. All you are guaranteed to be able to do in the signal-handling function, without causing undefined behavior, is to call signal, and to assign a value to a volatile static object of the type sig_atomic_t.
The first few times I ran this program, on Ubuntu Linux, it looked like your call to alarm in the signal handler didn't work, so the loop in main just kept running after the first alarm. When I tried it later, the program ran the signal handler a few times, and then hung. All this is consistent with undefined behavior: the program fails, sometimes, and in various more or less interesting ways.
It is not uncommon for programs that have undefined behavior to work differently in the debugger. The debugger is a different environment, and your program and data could for example be laid out in memory in a different way, so errors can manifest themselves in a different way, or not at all.
I got the program to work by adding a variable:
volatile sig_atomic_t got_interrupt = 0;
And then I changed your signal handler to this very simple one:
void sig_alarm(int signo) {
got_interrupt = 1;
}
And then I inserted the actual work into the infinite loop in main:
if (got_interrupt) {
got_interrupt = 0;
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
perror("getpwnam error");
alarm(1);
}
I think the "apue" you mention is the book "Advanced Programming in the UNIX Environment", which I don't have here, so I don't know if the purpose of this example is to show that you shouldn't mess around with things inside of a signal handler, or just that signals can cause problems by interrupting the normal work of the program.
According to the spec, the function getpwnam is not reentrant and is not guaranteed to be thread safe. Since you are accessing the structure in two different threads of control (signal handlers are effectively running in a different thread context), you are running into this issue. Whenever you have concurrent or parallel execution (as when using pthreads or when using a signal handler), you must be sure not to modify shared state (e.g. the structure owned by 'getpwnam'), and if you do, then appropriate locking/synchronization must be used.
Additionally, the signal function has been deprecated in favor of the sigaction function. In order to ensure portable behavior when registering signal handlers, you should always use the sigaction invocation.
Using the sigaction function, you can use the SA_RESETHAND flag to reset the default handler. You can also use the sigprocmask function to enable/disable the delivery of signals without modifying their handlers.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void sigalrm_handler(int);
int main()
{
signal(SIGALRM, sigalrm_handler);
alarm(3);
while(1)
{
}
return 0;
}
void sigalrm_handler(int sign)
{
printf("I am alive. Catch the sigalrm %d!\n",sign);
alarm(3);
}
For example, my code is runing in main doing nothing and every 3 seconds my program says im alive x)
I think that if you do as i done calling in the handler function alarm with value 3, the problem is resolved :)

Resources