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.
Related
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.
I want to write a C program that runs for a specified amount of seconds
say 10 seconds and then exits. The code should set up an interrupt to go
off after a specified amount of time has elapsed.
Here is my attempt. But I am not sure if SIGALRM is the correct way to do it.
Can SIGALRM be called an interrupt?
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
void handler()
{
_exit(0);
}
int main()
{
signal(SIGALRM, handler);
alarm(10);
for (;;); /* You can assume that for(;;); is just a dummy code. The main idea is to insert something into code. Whatever code it may be so that it stops after 10 seconds – */
return 0;
}
Any suggestions/alternatives/better way to achieve this?
The wording "signal" vs. "interrupt" is not fully clear. Signals can interrupt system calls, so a signal is an interrupt in this sense. But a signal is not a hardware interrupt. Whan you use an operating system, normal programs often don't have direct access to hardware interrupts.
Calling _exit from the signal handler might be problematic if your program needs to finish a task or to clean up something.
I suggest to implement a graceful end by setting a flag. Additionally I suggest to use sigaction instead of signal, because the semantics of signal and signal handlers set up with this function is implementation-dependent.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
static volatile sig_atomic_t timeout = 0;
void handler(int sig)
{
(void) sig;
timeout = 1;
}
int main(void)
{
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = handler;
if(sigaction(SIGALRM, act, NULL) < 0)
{
// handle error
}
alarm(10);
while(!timeout /* and maybe other conditions */)
{
// do something, handle error return codes and errno (EINTR)
// check terminate flag as necessary
}
// clean up if necessary
return 0;
}
Explanation (as requested in a comment)
static volatile sig_atomic_t timeout = 0;
sig_atomic_t is a type that guarantees atomic access even in the presence of asynchronous interrupts made by signals. That means an access to the variable cannot be interrupted in between, i.e. the software will never see a partially modified value. (see https://en.cppreference.com/w/c/program/sig_atomic_t)
volatile informs the compiler not to optimize access to the variable. This is necessary because the signal handler may modify the value while the main function is running the loop that is intended to check the flag. Otherwise the compiler might optimize the access out of the loop condition and do it only once before the loop because the variable is never modified inside the loop. (see https://en.cppreference.com/w/c/language/volatile)
In my destructor I want to destroy a thread cleanly.
My goal is to wait for a thread to finish executing and THEN destroy the thread.
The only thing I found about querying the state of a pthread is pthread_attr_setdetachstate but this only tells you if your thread is:
PTHREAD_CREATE_DETACHED
PTHREAD_CREATE_JOINABLE
Both of those have nothing to do with whether the thread is still running or not.
How do you query a pthread to see if it is still running?
It sounds like you have two questions here:
How can I wait until my thread completes?
Answer: This is directly supported by pthreads -- make your thread-to-be-stopped JOINABLE (when it is first started), and use pthread_join() to block your current thread until the thread-to-be-stopped is no longer running.
How can I tell if my thread is still running?
Answer: You can add a "thread_complete" flag to do the trick:
Scenario: Thread A wants to know if Thread B is still alive.
When Thread B is created, it is given a pointer to the "thread_complete" flag address. The "thread_complete" flag should be initialized to NOT_COMPLETED before the thread is created. Thread B's entry point function should immediately call pthread_cleanup_push() to push a "cleanup handler" which sets the "thread_complete" flag to COMPLETED.
See details about cleanup handlers here: pthread cleanup handlers
You'll want to include a corresponding pthread_cleanup_pop(1) call to ensure that the cleanup handler gets called no matter what (i.e. if the thread exits normally OR due to cancellation, etc.).
Then, Thread A can simply check the "thread_complete" flag to see if Thread B has exited yet.
NOTE: Your "thread_complete" flag should be declared "volatile" and should be an atomic type -- the GNU compilers provide the sig_atomic_t for this purpose. This allows the two threads consistent access the same data without the need for synchronization constructs (mutexes/semaphores).
pthread_kill(tid, 0);
No signal is sent, but error checking is still performed so you can use that to check
existence of tid.
CAUTION: This answer is incorrect. The standard specifically prohibits passing the ID of a thread whose lifetime has ended. That ID might now specify a different thread or, worse, it might refer to memory that has been freed, causing a crash.
I think all you really need is to call pthread_join(). That call won't return until the thread has exited.
If you only want to poll to see whether the thread is still running or not (and note that is usually not what you should be wanting to do!), you could have the thread set a volatile boolean to false just before it exits... then your main-thread could read the boolean and if it's still true, you know the thread is still running. (if it's false, on the other hand, you know the thread is at least almost gone; it may still be running cleanup code that occurs after it sets the boolean to false, though, so even in this case you should still call pthread_join before trying to free any resources the thread might have access to)
There is not fully portable solution, look if your platform supports pthread_tryjoin_np or pthread_timedjoin_np. So you just check if thread can be joined (of course created with PTHREAD_CREATE_JOINABLE).
Let me note on the "winning" answer, which has a huge hidden flaw, and in some contexts it can lead to crashes. Unless you use pthread_join, it will coming up again and again. Assume you are having a process and a shared library. Call the library lib.so.
You dlopen it, you start a thread in it. Assume you don't want it join to it, so you set it detachable.
Process and shared lib's logic doing its work, etc...
You want to load out lib.so, because you don't need it any more.
You call a shutdown on the thread and you say, that you want to read a flag afterwards from your lib.so's thread, that it have finished.
You continue on another thread with dlclose, because you see, that you have saw, that the flag is now showing the thread as "finished"
dlclose will load out all stack and code related memory.
Whops, but dlclose does not stop threads. And you know, even when you are in the last line of the cleanup handler to set the "thread is finished" volatile atomic flag variable, you still have to return from a lot of methods on the stack, giving back values, etc. If a huge thread priority was given to #5+#6's thread, you will receive dlclose before you could REALLY stop on the thread. You will have some nice crashes sometimes.
Let me point out, that this is not a hipothetical problem, I had the same issue on our project.
I believe I've come up with a solution that at least works for Linux. Whenever I create a thread I have it save it's LWP (Light Weight Process ID) and assign it a unique name, eg.
int lwp = syscall(SYS_gettid);
prctl(PR_SET_NAME, (long)"unique name", 0, 0, 0);
Then, to check if the thread exists later I open /proc/pid/task/lwp/comm and read it. If the file exists and it's contents match the unique name I assigned, the thread exists. Note that this does NOT pass a possibly defunct/reused TID to any library function, so no crashes.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <sys/file.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <syscall.h>
pthread_t subthread_tid;
int subthread_lwp;
#define UNIQUE_NAME "unique name"
bool thread_exists (pthread_t thread_id)
{
char path[100];
char thread_name[16];
FILE *fp;
bool thread_exists = false;
// If the /proc/<pid>/task/<lwp>/comm file exists and it's contents match the "unique name" the
// thread exists, and it's the original thread (TID has NOT been reused).
sprintf(path, "/proc/%d/task/%d/comm", getpid(), subthread_lwp);
fp = fopen(path, "r");
if( fp != NULL ) {
fgets(thread_name, 16, fp);
fclose(fp);
// Need to trim off the newline
thread_name[strlen(thread_name)-1] = '\0';
if( strcmp(UNIQUE_NAME, thread_name) == 0 ) {
thread_exists = true;
}
}
if( thread_exists ) {
printf("thread exists\n");
} else {
printf("thread does NOT exist\n");
}
return thread_exists;
}
void *subthread (void *unused)
{
subthread_lwp = syscall(SYS_gettid);
prctl(PR_SET_NAME, (long)UNIQUE_NAME, 0, 0, 0);
sleep(10000);
return NULL;
}
int main (int argc, char *argv[], char *envp[])
{
int error_number;
pthread_create(&subthread_tid, NULL, subthread, NULL);
printf("pthread_create()\n");
sleep(1);
thread_exists(subthread_tid);
pthread_cancel(subthread_tid);
printf("pthread_cancel()\n");
sleep(1);
thread_exists(subthread_tid);
error_number = pthread_join(subthread_tid, NULL);
if( error_number == 0 ) {
printf("pthread_join() successful\n");
} else {
printf("pthread_join() failed, %d\n", error_number);
}
thread_exists(subthread_tid);
exit(0);
}
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
void* thread1 (void* arg);
void* thread2 (void* arg);
int main()
{
pthread_t thr_id;
pthread_create(&thr_id, NULL, thread1, NULL);
sleep(10);
}
void* thread1 (void* arg)
{
pthread_t thr_id = 0;
pthread_create(&thr_id, NULL, thread2, NULL);
sleep(5);
int ret = 0;
if( (ret = pthread_kill(thr_id, 0)) == 0)
{
printf("still running\n");
pthread_join(thr_id, NULL);
}
else
{
printf("RIP Thread = %d\n",ret);
}
}
void* thread2 (void* arg)
{
// sleep(5);
printf("I am done\n");
}
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()
In my destructor I want to destroy a thread cleanly.
My goal is to wait for a thread to finish executing and THEN destroy the thread.
The only thing I found about querying the state of a pthread is pthread_attr_setdetachstate but this only tells you if your thread is:
PTHREAD_CREATE_DETACHED
PTHREAD_CREATE_JOINABLE
Both of those have nothing to do with whether the thread is still running or not.
How do you query a pthread to see if it is still running?
It sounds like you have two questions here:
How can I wait until my thread completes?
Answer: This is directly supported by pthreads -- make your thread-to-be-stopped JOINABLE (when it is first started), and use pthread_join() to block your current thread until the thread-to-be-stopped is no longer running.
How can I tell if my thread is still running?
Answer: You can add a "thread_complete" flag to do the trick:
Scenario: Thread A wants to know if Thread B is still alive.
When Thread B is created, it is given a pointer to the "thread_complete" flag address. The "thread_complete" flag should be initialized to NOT_COMPLETED before the thread is created. Thread B's entry point function should immediately call pthread_cleanup_push() to push a "cleanup handler" which sets the "thread_complete" flag to COMPLETED.
See details about cleanup handlers here: pthread cleanup handlers
You'll want to include a corresponding pthread_cleanup_pop(1) call to ensure that the cleanup handler gets called no matter what (i.e. if the thread exits normally OR due to cancellation, etc.).
Then, Thread A can simply check the "thread_complete" flag to see if Thread B has exited yet.
NOTE: Your "thread_complete" flag should be declared "volatile" and should be an atomic type -- the GNU compilers provide the sig_atomic_t for this purpose. This allows the two threads consistent access the same data without the need for synchronization constructs (mutexes/semaphores).
pthread_kill(tid, 0);
No signal is sent, but error checking is still performed so you can use that to check
existence of tid.
CAUTION: This answer is incorrect. The standard specifically prohibits passing the ID of a thread whose lifetime has ended. That ID might now specify a different thread or, worse, it might refer to memory that has been freed, causing a crash.
I think all you really need is to call pthread_join(). That call won't return until the thread has exited.
If you only want to poll to see whether the thread is still running or not (and note that is usually not what you should be wanting to do!), you could have the thread set a volatile boolean to false just before it exits... then your main-thread could read the boolean and if it's still true, you know the thread is still running. (if it's false, on the other hand, you know the thread is at least almost gone; it may still be running cleanup code that occurs after it sets the boolean to false, though, so even in this case you should still call pthread_join before trying to free any resources the thread might have access to)
There is not fully portable solution, look if your platform supports pthread_tryjoin_np or pthread_timedjoin_np. So you just check if thread can be joined (of course created with PTHREAD_CREATE_JOINABLE).
Let me note on the "winning" answer, which has a huge hidden flaw, and in some contexts it can lead to crashes. Unless you use pthread_join, it will coming up again and again. Assume you are having a process and a shared library. Call the library lib.so.
You dlopen it, you start a thread in it. Assume you don't want it join to it, so you set it detachable.
Process and shared lib's logic doing its work, etc...
You want to load out lib.so, because you don't need it any more.
You call a shutdown on the thread and you say, that you want to read a flag afterwards from your lib.so's thread, that it have finished.
You continue on another thread with dlclose, because you see, that you have saw, that the flag is now showing the thread as "finished"
dlclose will load out all stack and code related memory.
Whops, but dlclose does not stop threads. And you know, even when you are in the last line of the cleanup handler to set the "thread is finished" volatile atomic flag variable, you still have to return from a lot of methods on the stack, giving back values, etc. If a huge thread priority was given to #5+#6's thread, you will receive dlclose before you could REALLY stop on the thread. You will have some nice crashes sometimes.
Let me point out, that this is not a hipothetical problem, I had the same issue on our project.
I believe I've come up with a solution that at least works for Linux. Whenever I create a thread I have it save it's LWP (Light Weight Process ID) and assign it a unique name, eg.
int lwp = syscall(SYS_gettid);
prctl(PR_SET_NAME, (long)"unique name", 0, 0, 0);
Then, to check if the thread exists later I open /proc/pid/task/lwp/comm and read it. If the file exists and it's contents match the unique name I assigned, the thread exists. Note that this does NOT pass a possibly defunct/reused TID to any library function, so no crashes.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <sys/file.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <syscall.h>
pthread_t subthread_tid;
int subthread_lwp;
#define UNIQUE_NAME "unique name"
bool thread_exists (pthread_t thread_id)
{
char path[100];
char thread_name[16];
FILE *fp;
bool thread_exists = false;
// If the /proc/<pid>/task/<lwp>/comm file exists and it's contents match the "unique name" the
// thread exists, and it's the original thread (TID has NOT been reused).
sprintf(path, "/proc/%d/task/%d/comm", getpid(), subthread_lwp);
fp = fopen(path, "r");
if( fp != NULL ) {
fgets(thread_name, 16, fp);
fclose(fp);
// Need to trim off the newline
thread_name[strlen(thread_name)-1] = '\0';
if( strcmp(UNIQUE_NAME, thread_name) == 0 ) {
thread_exists = true;
}
}
if( thread_exists ) {
printf("thread exists\n");
} else {
printf("thread does NOT exist\n");
}
return thread_exists;
}
void *subthread (void *unused)
{
subthread_lwp = syscall(SYS_gettid);
prctl(PR_SET_NAME, (long)UNIQUE_NAME, 0, 0, 0);
sleep(10000);
return NULL;
}
int main (int argc, char *argv[], char *envp[])
{
int error_number;
pthread_create(&subthread_tid, NULL, subthread, NULL);
printf("pthread_create()\n");
sleep(1);
thread_exists(subthread_tid);
pthread_cancel(subthread_tid);
printf("pthread_cancel()\n");
sleep(1);
thread_exists(subthread_tid);
error_number = pthread_join(subthread_tid, NULL);
if( error_number == 0 ) {
printf("pthread_join() successful\n");
} else {
printf("pthread_join() failed, %d\n", error_number);
}
thread_exists(subthread_tid);
exit(0);
}
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
void* thread1 (void* arg);
void* thread2 (void* arg);
int main()
{
pthread_t thr_id;
pthread_create(&thr_id, NULL, thread1, NULL);
sleep(10);
}
void* thread1 (void* arg)
{
pthread_t thr_id = 0;
pthread_create(&thr_id, NULL, thread2, NULL);
sleep(5);
int ret = 0;
if( (ret = pthread_kill(thr_id, 0)) == 0)
{
printf("still running\n");
pthread_join(thr_id, NULL);
}
else
{
printf("RIP Thread = %d\n",ret);
}
}
void* thread2 (void* arg)
{
// sleep(5);
printf("I am done\n");
}