How many ways will a process be terminated in Linux? - linux

I'm reading Advanced Programming in the Unix Environment 3rd Edn, ยง7.3, Process Termination, the following statement make me confused:
There are eight ways for a process to terminate. Normal termination
occurs in five ways:
Return from main
Calling exit
Calling _exit or _Exit
Return of the last thread from its start routine (Section 11.5)
Calling pthread_exit (Section 11.5) from the last thread
for
Return of the last thread from its start routine (Section 11.5)
Calling pthread_exit (Section 11.5) from the last thread
I don't think a process will terminate if it is not returned form main function even though the last thread in this process is terminated, am I right? If not, why 4 and 5 are right?

The main thread is one of the threads. For example, in
void *start(void *arg) {
sleep(1);
pthread_exit(0);
}
int main() {
pthread_t t;
pthread_create(&t, 0, start, 0);
pthread_exit(0);
}
the main thread exits immediately, but the process continues running until the last thread has exited. This is true the other way around,
void *start(void *arg) {
pthread_exit(0);
}
int main() {
pthread_t t;
pthread_create(&t, 0, start, 0);
sleep(1);
pthread_exit(0);
}
where the main thread is the last one left.

Related

Whats exact definition of 'atomicity' in programming?

the definition of 'atomicity' says that a transaction should be able to be terminated without being touched or manipulated by possibly concurrent running actions during its process. But does that also mean that a program should not run concurrent when it is supposed to be atomic?
let's say we have 2 program as an example:
example_program1:
counts int i = 1 to 100 every second
every number is printed in new line
example_program2:
just prints "hi"
and a parent program that includes both of these program and run them once receiving a signal to start a specific program (e.g via sigaction in linux) with 2 version:
version 1:
runs the program (even concurrent) anytime once receiving the signal
which means program2 can print "hi" while program1 is still printing out the numbers
version 2:
only run one program at a time
signal for other program is blocked until program in progress has terminated
in this example, can only version 2 considered atomic or both? Would this program be non-atomic only if e.g program2 would increment i by 1 during its process?
Hi Atomic operations provide instructions that execute atomically without interruption. Just as the atom was originally thought to be an indivisible particle, atomic operations are indivisible instructions.
I will like to explain that with a program multithread production and consumer with rase conditions.
#include <stdio.h>
#include <pthread.h>
pthread_cond_t condicion = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int cont = 0;
void* productor(){
while(1){
pthread_mutex_lock(&mutex);
while(cont != 0)
{
pthread_cond_wait(&condicion, &mutex);
}
cont++;
printf("%d\n",cont);
pthread_cond_signal(&condicion);
pthread_mutex_unlock(&mutex);
}
}
void* consumidor(){
while(1)
{
pthread_mutex_lock(&mutex);
while(cont == 0)
{
pthread_cond_wait(&condicion, &mutex);
}
cont--;
printf("%d\n",cont);
pthread_cond_signal(&condicion);
pthread_mutex_unlock(&mutex);
}
}
int main(){
pthread_t id_hilo1,id_hilo2;
pthread_create(&id_hilo1, NULL, &productor, NULL);
pthread_create(&id_hilo2, NULL, &consumidor, NULL);
pthread_join(id_hilo1, NULL);
pthread_join(id_hilo2, NULL);
return 0;
}

Solaris thr_join vs posix pthread_join

In Solaris, thr_join documentation states the following:
int thr_join(thread_t thread, thread_t *departed, void
**status);
If the target thread ID is 0, thr_join() finds and returns
the status of a terminated undetached thread in the process.
Is POSIX pthread_join equivalent?
int pthread_join(pthread_t thread, void **status);
suspends processing of the calling thread until the target thread completes
How can I use pthread_join in case of thr_join when I would like to know which child thread have terminated among many.
Is there any other alternative?
In other words, if a parent thread spawns N child threads, how do the parent thread know by polling or something else which thread has exited / terminated?
Is POSIX pthread_join equivalent?
Yes, it's equivalent. Well, close enough. You can see the differences in the implementation:
int
thr_join(thread_t tid, thread_t *departed, void **status)
{
int error = _thrp_join(tid, departed, status, 1);
return ((error == EINVAL)? ESRCH : error);
}
/*
* pthread_join() differs from Solaris thr_join():
* It does not return the departed thread's id
* and hence does not have a "departed" argument.
* It returns EINVAL if tid refers to a detached thread.
*/
#pragma weak _pthread_join = pthread_join
int
pthread_join(pthread_t tid, void **status)
{
return ((tid == 0)? ESRCH : _thrp_join(tid, NULL, status, 1));
}
They're even implemented using the same internal function.
But you don't want to use Solaris threads. Just use POSIX threads.

reacting to two signals sent to the CPU in linux

I wrote the following code:
void handler (int signal) {
if (signal==SIGVTALRM) {
printf("one second passed\n");
}
if (signal==SIGALRM) {
alarm(1);
//printf("curret context is %ld\n" , thread_tbl[currThreadNum].uc.uc_mcontext.cr2);
currThreadNum=(currThreadNum+1)%THREAD_NUM;
printf("switching from thread #%d to thread #%d\n", ((currThreadNum-1+THREAD_NUM)%THREAD_NUM), currThreadNum);
printf("current thread number is %d\n", currThreadNum);
thread_tbl[(currThreadNum-1+THREAD_NUM)%THREAD_NUM].vtime=+1000;
swapcontext( &(thread_tbl[ (currThreadNum-1+THREAD_NUM)%THREAD_NUM ].uc), &(thread_tbl[currThreadNum ].uc) );
}
}
int ut_start(void) {
int i=0;
struct sigaction sa;
struct itimerval itv;
// set the signal
sa.sa_flags=SA_RESTART;
sigfillset(&sa.sa_mask);
sa.sa_handler = handler;
itv.it_interval.tv_sec=0;
itv.it_interval.tv_usec=100;
itv.it_value=itv.it_interval;
if (sigaction(SIGALRM, &sa, NULL)<0) {
abort();
}
if (sigaction(SIGVTALRM, &sa, NULL)<0) {
abort();
}
setitimer(ITIMER_VIRTUAL, &itv, NULL);
for(i=0; i<TAB_SIZE; i++) {
getcontext(&thread_tbl[i].uc); // get the context the content of current thread
makecontext(&thread_tbl[i].uc, (void(*)(void))func ,1, i); // when this context is activated, func will be executed and then uc.uc_link will get control
}
//start running
alarm(1);
currThreadNum=0;
//printf("currThreadNum=0\n");
swapcontext(&temp_context, &thread_tbl[0].uc);
}
My purpose was to write a program that responds to both SIGVTALRM signal and SIGALRM. However, when I run the program, it seems that the program only react to SIGALRM signals.
In the function ut_start() I started a timer that resets every 100 usec. I don't see any evidence that it works.
One more thing, how can debug this program so I can actually see the timer has started? Is there any variable that I can see in debug mode that tells me something about the status of the timer?
I think I found the answer by myself.
The functions I supplies are only a part of my program. Somewhere in the program, I used the function sleep().
According to the documentation of sleep (http://linux.die.net/man/3/sleep):
sleep() may be implemented using SIGALRM; mixing calls to alarm(2) and
sleep() is a bad idea.Using longjmp(3) from a signal handler or
modifying the handling of SIGALRM while sleeping will cause undefined
results.
When I removed the sleep() function, everything was OK.

Keeping threads alive even if the main thead has terminated

I am not sure if my question is correct, but I have the following example, where the main thread creates two additional threads.
Since I am not using join command at the end of the main, it will continue execution and in the same time, the two created threads will work in parallel. But since the main is terminated before they finish their execution, I am getting the following output:
terminate called without an active exception
Aborted (core dumped)
Here's the code:
#include <iostream> // std::cout
#include <thread> // std::thread
#include <chrono>
void foo()
{
std::chrono::milliseconds dura( 2000 );
std::this_thread::sleep_for( dura );
std::cout << "Waited for 2Sec\n";
}
void bar(int x)
{
std::chrono::milliseconds dura( 4000 );
std::this_thread::sleep_for( dura );
std::cout << "Waited for 4Sec\n";
}
int main()
{
std::thread first (foo);
std::thread second (bar,0);
return 0;
}
So my question is how to keep these two threads working even if the main thread terminated?
I am asking this because in my main program, I have an event handler ,and for each event I create a corresponding thread. But the main problem when the handler creates a new thread, the handler will continue execution. Until it is destroyed which will cause also the newly created thread to be destroyed. So my question is how to keep the thread alive in this case?
Also if I use a join it will convert back to serialization.
void ho_commit_indication_handler(message &msg, const boost::system::error_code &ec)
{
.....
}
void event_handler(message &msg, const boost::system::error_code &ec)
{
if (ec)
{
log_(0, __FUNCTION__, " error: ", ec.message());
return;
}
switch (msg.mid())
{
case n2n_ho_commit:
{
boost::thread thrd(&ho_commit_indication_handler, boost::ref(msg), boost::ref(ec));
}
break
}
};
Thanks a lot.
Keeping the threads alive is a bad idea, because it causes a call to std::terminate. You should definitively join the threads:
int main()
{
std::thread first (foo);
std::thread second (bar, 0);
first.join();
second.join();
}
An alternative is to detach the threads. However you still need to assert that the main thread lives longer (by e.g. using a mutex / condition_variable).
This excerpt from the C++11 standard is relevant here:
15.5.1 The std::terminate() function [except.terminate]
1 In some situations exception handling must be abandoned for less subtle error
handling techniques. [ Note: These situations are:
[...]
-- when the destructor or the copy assignment operator is invoked on an
object of type std::thread that refers to a joinable thread
Hence, you have to call either join or detach on threads before scope exit.
Concerning your edit: You have to store the threads in a list (or similar) and wait for every one of them before main is done. A better idea would be to use a thread pool (because this limits the total number of threads created).

pthread_cond_broadcast problem

Using pthreads in linux 2.6.30 I am trying to send a single signal which will cause multiple threads to begin execution. The broadcast seems to only be received by one thread. I have tried both pthread_cond_signal and pthread cond_broadcast and both seem to have the same behavior. For the mutex in pthread_cond_wait, I have tried both common mutexes and separate (local) mutexes with no apparent difference.
worker_thread(void *p)
{
// setup stuff here
printf("Thread %d ready for action \n", p->thread_no);
pthread_cond_wait(p->cond_var, p->mutex);
printf("Thread %d off to work \n", p->thread_no);
// work stuff
}
dispatch_thread(void *p)
{
// setup stuff
printf("Wakeup, everyone ");
pthread_cond_broadcast(p->cond_var);
printf("everyone should be working \n");
// more stuff
}
main()
{
pthread_cond_init(cond_var);
for (i=0; i!=num_cores; i++) {
pthread_create(worker_thread...);
}
pthread_create(dispatch_thread...);
}
Output:
Thread 0 ready for action
Thread 1 ready for action
Thread 2 ready for action
Thread 3 ready for action
Wakeup, everyone
everyone should be working
Thread 0 off to work
What's a good way to send signals to all the threads?
First off, you should have the mutex locked at the point where you call pthread_cond_wait(). It's generally a good idea to hold the mutex when you call pthread_cond_broadcast(), as well.
Second off, you should loop calling pthread_cond_wait() while the wait condition is true. Spurious wakeups can happen, and you must be able to handle them.
Finally, your actual problem: you are signaling all threads, but some of them aren't waiting yet when the signal is sent. Your main thread and dispatch thread are racing your worker threads: if the main thread can launch the dispatch thread, and the dispatch thread can grab the mutex and broadcast on it before the worker threads can, then those worker threads will never wake up.
You need a synchronization point prior to signaling where you wait to signal till all threads are known to be waiting for the signal. That, or you can keep signaling till you know all threads have been woken up.
In this case, you could use the mutex to protect a count of sleeping threads. Each thread grabs the mutex and increments the count. If the count matches the count of worker threads, then it's the last thread to increment the count and so signals on another condition variable sharing the same mutex to the sleeping dispatch thread that all threads are ready. The thread then waits on the original condition, which causes it release the mutex.
If the dispatch thread wasn't sleeping yet when the last worker thread signals on that condition, it will find that the count already matches the desired count and not bother waiting, but immediately broadcast on the shared condition to wake workers, who are now guaranteed to all be sleeping.
Anyway, here's some working source code that fleshes out your sample code and includes my solution:
#include <stdio.h>
#include <pthread.h>
#include <err.h>
static const int num_cores = 8;
struct sync {
pthread_mutex_t *mutex;
pthread_cond_t *cond_var;
int thread_no;
};
static int sleeping_count = 0;
static pthread_cond_t all_sleeping_cond = PTHREAD_COND_INITIALIZER;
void *
worker_thread(void *p_)
{
struct sync *p = p_;
// setup stuff here
pthread_mutex_lock(p->mutex);
printf("Thread %d ready for action \n", p->thread_no);
sleeping_count += 1;
if (sleeping_count >= num_cores) {
/* Last worker to go to sleep. */
pthread_cond_signal(&all_sleeping_cond);
}
int err = pthread_cond_wait(p->cond_var, p->mutex);
if (err) warnc(err, "pthread_cond_wait");
printf("Thread %d off to work \n", p->thread_no);
pthread_mutex_unlock(p->mutex);
// work stuff
return NULL;
}
void *
dispatch_thread(void *p_)
{
struct sync *p = p_;
// setup stuff
pthread_mutex_lock(p->mutex);
while (sleeping_count < num_cores) {
pthread_cond_wait(&all_sleeping_cond, p->mutex);
}
printf("Wakeup, everyone ");
int err = pthread_cond_broadcast(p->cond_var);
if (err) warnc(err, "pthread_cond_broadcast");
printf("everyone should be working \n");
pthread_mutex_unlock(p->mutex);
// more stuff
return NULL;
}
int
main(void)
{
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER;
pthread_t worker[num_cores];
struct sync info[num_cores];
for (int i = 0; i < num_cores; i++) {
struct sync *p = &info[i];
p->mutex = &mutex;
p->cond_var = &cond_var;
p->thread_no = i;
pthread_create(&worker[i], NULL, worker_thread, p);
}
pthread_t dispatcher;
struct sync p = {&mutex, &cond_var, num_cores};
pthread_create(&dispatcher, NULL, dispatch_thread, &p);
pthread_exit(NULL);
/* not reached */
return 0;
}

Resources