Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Should pthread_exit() be used in main()?

1,442 views
Skip to first unread message

Sunnz

unread,
Jun 3, 2009, 12:18:45 AM6/3/09
to
Hi,

I just started learning pthreads, and are little confused with
pthread_exit(), namely, when should it be used?

I have written very basic codes to try to understand how it works:
http://pastebin.com/m79438632

Here if you comment out pthread_exit() in main(), all the child threads
don't get to finish, unless you uncomment the for loop that joins all
child threads.

So does pthread_exit() does that for you? That the process and its
threads doesn't get killed till all threads has 'finished'?

Should PrintHello in the above example call pthread_exit()?

Dave Butenhof

unread,
Jun 3, 2009, 6:18:03 AM6/3/09
to

pthread_exit() causes the calling thread to terminate; just as calling
exit() causes the process to terminate.

Just as a process returning from main() implicitly calls exit(), most
threads implicitly call pthread_exit() on return from the thread start
routine. The exception is the initial thread, the one running main();
because if we had changed that behavior it would have affected existing
non-threaded programs as well.

So if you want the initial process thread to terminate, leaving other
threads in the process to continue operation, you need to explicitly
call pthread_exit() rather than returning from main().

Aside from that, if your application architecture is such that it makes
sense to cause the current thread to terminate other than by returning
from the start routine, call pthread_exit(). If not... don't worry about it.

Specifically; in the example you cite, the pthread_exit() call from
PrintHello(), which is the thread start routine, is redundant; it could
just as easily have simply returned with the value NULL.

In main(), however, with the pthread_join() calls commented out, you do
need the pthread_exit() to ensure that the PrintHello() threads are
allowed to finish before the process evaporates. The process will go
away automatically when the last thread terminates; but you have no
control over the process exit status in this case. If you care about the
process exit status, you should use pthread_join() to ensure that all
your threads have created, and then either return from main() or call
exit() with the desired exit status.

However, main(), except for the call stack arrangement that happens to
lead to the implicit exit() call on return, is no different from any
other thread. If you want 4 threads each running PrintHello(), and you
have nothing in particular for the initial thread to do after launching
other threads, you might as well make IT one of those 4 by simply making
(NUM_THREADS - 1) calls to pthread_create(), and then calling
PrintHello() with an appropriate argument. When the call returns to
main(), it can wait for the other threads to finish and exit, or simply
call pthread_exit() to let the process terminate passively when the last
is done. This performs the same job with less overhead. (Not that the
overhead of thread creation is important in this trivial I/O bound example.)

Sunnz

unread,
Jun 3, 2009, 7:53:33 AM6/3/09
to
Dave Butenhof 提到:

>
> Aside from that, if your application architecture is such that it makes
> sense to cause the current thread to terminate other than by returning
> from the start routine, call pthread_exit(). If not... don't worry about
> it.
>
> Specifically; in the example you cite, the pthread_exit() call from
> PrintHello(), which is the thread start routine, is redundant; it could
> just as easily have simply returned with the value NULL.
>

Right, so if "return NULL" was written in PrintHello() instead of
pthread_exit(), then it will implicitly call pthread_exit()?

So what actually would happen here when it calls pthread_exit() but
doesn't have a return? Would it simply terminate the thread without
returning anything? If so would it make more sense for start routines
that doesn't return anything?

> However, main(), except for the call stack arrangement that happens to
> lead to the implicit exit() call on return, is no different from any
> other thread. If you want 4 threads each running PrintHello(), and you
> have nothing in particular for the initial thread to do after launching
> other threads, you might as well make IT one of those 4 by simply making
> (NUM_THREADS - 1) calls to pthread_create(), and then calling
> PrintHello() with an appropriate argument. When the call returns to
> main(), it can wait for the other threads to finish and exit, or simply
> call pthread_exit() to let the process terminate passively when the last
> is done. This performs the same job with less overhead. (Not that the
> overhead of thread creation is important in this trivial I/O bound
> example.)

Thanks a lot for the clear explanation and the tips it surely helps a
lot for beginners like me!! :D

Dave Butenhof

unread,
Jun 4, 2009, 6:57:20 AM6/4/09
to
Sunnz wrote:
> Dave Butenhof 提到:
>>
>> Aside from that, if your application architecture is such that it
>> makes sense to cause the current thread to terminate other than by
>> returning from the start routine, call pthread_exit(). If not... don't
>> worry about it.
>>
>> Specifically; in the example you cite, the pthread_exit() call from
>> PrintHello(), which is the thread start routine, is redundant; it
>> could just as easily have simply returned with the value NULL.
>
> Right, so if "return NULL" was written in PrintHello() instead of
> pthread_exit(), then it will implicitly call pthread_exit()?

Let's say, at the risk of complication (but in the interest of
accuracy), simply that the net effect on the process state is the same
either way. Whether there's an ACTUAL call to pthread_exit() on return
from the start routine is unspecified, and irrelevant.

> So what actually would happen here when it calls pthread_exit() but
> doesn't have a return? Would it simply terminate the thread without
> returning anything? If so would it make more sense for start routines
> that doesn't return anything?

I'm not sure what you mean here. A thread start routine always returns a
value of type 'void *'. That is, even if your function doesn't return a
value (and you have a compiler that doesn't mind, or you've deliberately
used the wrong function prototype and either cast the function pointer
on pthread_create or, again, the compiler doesn't mind the mismatch),
the pthread library will interpret the appropriate location (register,
stack, or whatever depending on the machine call architecture) as a
return value, and store that to be queried by pthread_join().

That is, thread start functions ALWAYS return a value.

Calling pthread_exit(), which takes a similar void* value, will have the
same net effect on the internal pthread library data; and that value
will be made available to callers of pthread_join(). Again, if you
manage to fool the compiler to dispatch to the pthread_join entry point
without explicitly specifying a return value for the thread, the
function will still process an argument from the appropriate place; this
merely has an undefined value. (And I use the word "undefined" here
instead of "unspecified" in the strict standardese sense: for some call
architectures such an incorrect call could even result in a memory
access trap rather than merely an arbitrary value.)

In short, you CAN'T terminate a POSIX thread "without returning
anything"... it's not possible. By "fooling" the compiler you can write
code that you can pretend doesn't return anything; but there's still a
return value, and the thread library will handle it just the same.

>> However, main(), except for the call stack arrangement that happens to
>> lead to the implicit exit() call on return, is no different from any
>> other thread. If you want 4 threads each running PrintHello(), and you
>> have nothing in particular for the initial thread to do after
>> launching other threads, you might as well make IT one of those 4 by
>> simply making (NUM_THREADS - 1) calls to pthread_create(), and then
>> calling PrintHello() with an appropriate argument. When the call
>> returns to main(), it can wait for the other threads to finish and
>> exit, or simply call pthread_exit() to let the process terminate
>> passively when the last is done. This performs the same job with less
>> overhead. (Not that the overhead of thread creation is important in
>> this trivial I/O bound example.)
>
> Thanks a lot for the clear explanation and the tips it surely helps a
> lot for beginners like me!! :D

You're welcome. (And I hope the details you've provoked in the follow up
haven't made things a whole lot less clear. ;-) )

Andrew Gabriel

unread,
Jun 4, 2009, 11:29:05 AM6/4/09
to
In article <h05ikv$ffk$1...@usenet01.boi.hp.com>,

Dave Butenhof <david.b...@hp.com> writes:
> Sunnz wrote:
>> Hi,
>>
>> I just started learning pthreads, and are little confused with
>> pthread_exit(), namely, when should it be used?
>>
>> I have written very basic codes to try to understand how it works:
>> http://pastebin.com/m79438632
>>
>> Here if you comment out pthread_exit() in main(), all the child threads
>> don't get to finish, unless you uncomment the for loop that joins all
>> child threads.
>>
>> So does pthread_exit() does that for you? That the process and its
>> threads doesn't get killed till all threads has 'finished'?
>>
>> Should PrintHello in the above example call pthread_exit()?
>
> pthread_exit() causes the calling thread to terminate; just as calling
> exit() causes the process to terminate.
>
> Just as a process returning from main() implicitly calls exit(), most
> threads implicitly call pthread_exit() on return from the thread start
> routine. The exception is the initial thread, the one running main();
> because if we had changed that behavior it would have affected existing
> non-threaded programs as well.
>
> So if you want the initial process thread to terminate, leaving other
> threads in the process to continue operation, you need to explicitly
> call pthread_exit() rather than returning from main().

If no other thread is going to collect its exit status with a
pthread_join() you might want to detach it first for neatness
so you don't end up with a zombie thread...

pthread_detach(pthread_self());
pthread_exit(NULL);

--
Andrew Gabriel
[email address is not usable -- followup in the newsgroup]

Dave Butenhof

unread,
Jun 4, 2009, 12:37:02 PM6/4/09
to
Andrew Gabriel wrote:
> In article <h05ikv$ffk$1...@usenet01.boi.hp.com>,

>> So if you want the initial process thread to terminate, leaving other
>> threads in the process to continue operation, you need to explicitly
>> call pthread_exit() rather than returning from main().
>
> If no other thread is going to collect its exit status with a
> pthread_join() you might want to detach it first for neatness
> so you don't end up with a zombie thread...
>
> pthread_detach(pthread_self());
> pthread_exit(NULL);

Thereby adding, in neat order, the next level of complication. ;-)

And, to follow up on that, the second argument to pthread_create is a
pointer to an initialized pthread_attr_t; and if you know from the start
you'll have no need to join with a thread, simply create it detached in
the first place by using

pthread_attr_r attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, start, arg);

Of course, this would mean you have no choice to but terminate your
initial thread with pthread_exit()... because the other threads are
detached, you have no way to know when they're finished.

(Strictly, speaking, adding the next layer, there are plenty of ways to
synchronize with completion of a thread, and pthread_join represents
just one convenient example for the specific case where you care when
the thread is done and want a single value castable to (void*) from it.
There are a million other ways you could make the initial thread know
when the workers had finished, if you wanted; either more general or
possibly even more efficient.)

In your example, there's no point in detaching the threads. Either the
initial thread is exiting with pthread_exit(), and the process will
simply passively terminate when the last thread goes away; or you want
to join with each thread and terminate the process with a specific
status after the last one is done. In the first case, it doesn't matter
whether they're detached; in the second, if you detach you'd only need
to code the equivalent of pthread_join() yourself.

Andrew Gabriel

unread,
Jun 4, 2009, 6:18:29 PM6/4/09
to
In article <h08t7f$10k$1...@usenet01.boi.hp.com>,

Dave Butenhof <david.b...@hp.com> writes:
> Andrew Gabriel wrote:
>> In article <h05ikv$ffk$1...@usenet01.boi.hp.com>,
>>> So if you want the initial process thread to terminate, leaving other
>>> threads in the process to continue operation, you need to explicitly
>>> call pthread_exit() rather than returning from main().
>>
>> If no other thread is going to collect its exit status with a
>> pthread_join() you might want to detach it first for neatness
>> so you don't end up with a zombie thread...
>>
>> pthread_detach(pthread_self());
>> pthread_exit(NULL);
>
> Thereby adding, in neat order, the next level of complication. ;-)

I'm referring specifically to the case above, of the main thread
terminating.

A reason for terminating the main thread is that you don't get
the opportunity to set it up with non-default attributes, and if
all your threads are going to need specific attributes, then the
main thread may be of no use once it's started up the others.
Leaving it as a zombie means it continues to appear marked as such
in things like "prstat -L", but as I said, it's only for neatness.

0 new messages