POSIX threads and exiting from a thread - c

I have two threads, communicating with each other; each thread employs 'while(1) ..'. Now I need to let the threads exit upon a specific condition met, and therefore finish the application.
My question: is it safe to just 'return (NULL)' from the thread, or do I have to use 'pthread_exit' or 'pthread_join' functions as well?

It is safe to return null from the thread functions; the code that waits for them should be OK.
POSIX says of pthread_exit():
An implicit call to pthread_exit() is made when a thread other than the thread in which main() was first invoked returns from the start routine that was used to create it.
You do need something to wait for the thread with pthread_join() unless the thread was created with the detached attribute or detached later with pthread_detach().

Calling pthread_exit(NULL) and returning NULL at the end of the thread's initial function should be equivalent. However, doing either of these alone will lead to a resource leak. To avoid that, you must either call pthread_join on the thread from another thread, or put the thread in the detached state by calling pthread_detach on it or setting it to start in the detached state before creating it.

Related

Is it possible that pthread_cancel() terminates another unintended thread?

My question is similar to this one. But after viewing all its answers, I still don't know what kind of safety guarantee one can get with pthread_cancel(). So I would like to ask a more specific question:
Say that pthread_cancel() is called on a pthread_t variable, named my_thread, is it possible that by the time pthread_cancel(my_thread) is executed, the actual thread corresponding to my_thread has already been terminated somehow, and the kernel recycled the value of my_thread for another newly created thread, such that by executing pthread_cancel(my_thread), another unintended thread gets killed?
The value can't be "recycled" until the thread is detached or joined. As long as you didn't do either of those things, it's safe to call pthread_cancel, even if the thread already terminated.
The question is about race conditions involving pthread_cancel(). POSIX requires that function to be thread safe in the specific, limited sense in which it uses that term, but that doesn't really speak to the question at hand. The key details are specified in XSH 2.9.2, as #R.. observed earlier in a comment. In particular:
The lifetime of a thread ID ends after the thread terminates if it was
created with the detachstate attribute set to PTHREAD_CREATE_DETACHED
or if pthread_detach() or pthread_join() has been called for that
thread. A conforming implementation is free to reuse a thread ID after
its lifetime has ended. If an application attempts to use a thread ID
whose lifetime has ended, the behavior is undefined.
So an application is permitted to re-use thread IDs whose lifetime has ended, but that's really a side issue because if you attempt to use a stale one then the behavior is undefined, whether the ID has been reused or not. And of course, one of the innumerable possible manifestations of UB that could ensue in the case described is indeed that a different thread is cancelled than the one you meant to cancel, regardless of whether the thread ID has been reused.
The lifetime of a thread ID ends when the thread it identifies terminates if that thread was created detached, or when it is passed to either pthread_detach or pthread_join if the thread was created joinable. It is entirely possible to have a race between that and the execution of pthread_cancel. If the thread was created joinable then you need at least three threads total for that, but if it was created detached then you don't need any other than the one calling pthread_cancel and a separate one being cancelled. Either way pthread_cancel is risky.
The accepted answer to the question you linked is misleading, at best, but #DavidSchwartz's comment on it is much more useful, even if I don't think it accurately reflects the specification in every detail. Here is how I would put it:
It is safe to cancel a thread with pthread_cancel if one of these cases holds:
the thread was created joinable, and it is certain that it cannot have been detached or joined before the pthread_cancel call completes, or
the thread was created detached, and it is certain that it cannot have terminated, nor have been passed to pthread_join or pthread_attach (regardless of the success of these calls) before the pthread_cancel call completes.
It is not safe (i.e. it risks UB) to attempt to cancel
a thread that was created joinable, via the thread ID provided by pthread_create, if it is possible for that thread to be detached or joined before the pthread_cancel call completes, or
a thread that was created detached, if it is possible for that thread to terminate or have pthread_join or pthread_detach called on it before the pthread_cancel call completes.
It is unclear whether it is safe to cancel a thread that was created joinable and later detatched, via a thread ID obtained from pthread_self() after the detachment, if it is certain that neither pthread_join nor pthread_detach can have been called on that thread ID before the `pthread_cancel completes.*
*One could interpret the specifications to imply that under those circumstances, pthread_self returns a thread ID whose lifetime has already ended, so that the cancellation would definitely produce UB. But there are at least a couple different contrary interpretations, and under any of those, there is no defined condition under which the lifetime of the thread ID from pthread_self ends before the end of the program, leaving it safe to cancel the thread via that ID at any time.

Multithreading in C/C++ without waiting for the thread to finish

All the examples that I have seen about multithreading uses this method in the main method to wait until the thread is done:
pthread_join(thread_id, NULL);
But what if I don't want it to wait? I want my main function to continue as the thread is doing it's work, but at the same time, I don't want main to exit before the thread exists. Is this possible in C/C++?
If you want to avoid using pthread_join(), then pthread_detach() is an option.
From man-page:
int pthread_detach(pthread_t thread);
The pthread_detach() function marks the thread identified by thread
as detached. When a detached thread terminates, its resources are
automatically released back to the system without the need for
another thread to join with the terminated thread.
it does not prevent the thread from being
terminated if the process terminates using exit(3) (or equivalently,
if the main thread returns).

Can I close/terminate an running thread from its thread function?

I have created a thread, with a custom thread function. I have a condition in the thread function that if it becomes true, I want to close the thread from inside the thread function.
Is it possible?
You can return from the thread and if you want to return some value, you can use pthread_join on that thread.
I assume you are using pthread for the thread functionlaity. You can call the pthread_detach() function in your custom thread function after creating the thread. In the created thread just returning from the thread function will be sufficient to close the thread and release all the resources associated with the thread.
For PThreads there are two ways to end a thread cleanly.
Detached the thread using pthread_detach(). To end it then call pthread_exit(). To find a thread's phtread-id from inside the thread itself use phtread_self().
Call pthread_exit() and have another thread call pthread_join() on the pthread-id received when creating the thread that ended.
If you miss to call pthread_join() on a thread not having been detached by calling pthread_detach(), the resources in use by the thread will not be released, even after the thread ended.
This could lead to a shortage on memory and/or other system resources. Take care this does not happen.
A third was to end a thread is to just cancel it using pthread_cancel(), which typically isn't initated by the thread itself (as I could just use one of the two ways described above to end itself), but from another thread in the situation where the thread to end is not aware of this and could not be notified to do so.
The need to cancel a thread should rarely arise, and if it does one might start to overthink the program's design.

TerminateThread() returns error when terminating the thread

I have a ThreadA created using the CreateThread function. Inside ThreadA, another thread, ThreadB is created using the CreateThread function.
Now, I want to terminate ThreadB from ThreadA but the TerminateThread function fails.
Is it because ThreadA may not have the right to terminate ThreadB? I am really confused with this situation.
In general, never use TerminateThread because you can leave locks held and cause all sorts of problems. As MSDN says:
What you can do instead is to make your thread wait on an event object, which you can use to signal termination from another thread.
If you need to perform a periodic check for a terminate signal within some normal thread processing, you can set a wait timeout of zero so your thread can do still work while waiting to be terminated.
An example is in this SO answer here.

calling a thread function both as detached and as joinable from different parts of the code in C

i'm writing in C (gcc) and I have a function read_serial_device() that will be called as thread. I'm using the pthread library.
Thing is in main() i call this fn and I know i don't need to wait for it to exit. so I can instantiate it in DETACHABLE state.
however in other parts of the code (from another thread actually), i need to create it joinable.
Can I actually call the function as detachable in one case and as joinable in the other? or should I create it joinable always and everywhere?
thank you
Whether the thread is detached or not is a property of the thread, not the thread function... so nothing is stopping you from creating threads with different attributes that use the same thread function. The same goes for stack sizes, signal masks, and anything else you can set outside the thread function itself before/when you create the thread.

Resources