My question is similar to How do I check if a thread is terminated when using pthread?. but i did not quite get an answer.
My problem is...I create a certain number of threads say n. As soon as main detects the exit of any one thread it creates another thread thus keeping the degree of concurrency as n and so on.
How does the main thread detect the exit of a thread. pthread_join waits for a particular thread to exit but in my case it can be any one of the n threads.
Thanks
Most obvious, without restructuring your code as aix suggests, is to have each thread set something to indicate that it has finished (probably a value in an array shared between all threads, one slot per worker thread), and then signal a condition variable. Main thread waits on the condition variable and each time it wakes up, handle all threads that have indicated themselves finished: there may be more than one.
Of course that means that if the thread is cancelled you never get signalled, so use a cancellation handler or don't cancel the thread.
There are several ways to solve this.
One natural way is to have a thread pool of fixed size n and have a queue into which the main thread would place tasks and from which the workers would pick up tasks and process them. This will maintain a constant degree of concurrency.
An alternative is to have a semaphore with the initial value set to n. Every time a worker thread is created, the value of the semaphore would need to be decremented. Whenever a worker is about to terminate, it would need to increment ("post") the semaphore. Now, waiting on the semaphore in the main thread will block until there's fewer than n workers left; a new worker thread would then be spawned and the wait resumed. Since you won't be using pthread_join on the workers, they should be detached (pthread_detach).
If you want to be informed of a thread exiting (via pthread_exit or cancellation), you can use a handler with pthread_cleanup_push to inform the main thread of the child exiting (via a condition variable, semaphore or similar) so it can either wait on it, or simply start a new one (assuming the child is detached first).
Alternately, I'd suggest having the threads wait for more work (as suggested by #aix), rather than ending.
If your parent thread needs to do other other things, then it can't just constantly be blocking on pthread_join, You will need a way to send a message to the main thread from the child thread to tell it to call pthread_join. There are a number of IPC mechanisms that you could use for this.
When a child thread has done it's work, it would then send some sort of message to the main thread through IPC saying "I completed my job" and also pass its own thread id, then the main thread knows to call pthread_join on that thread id.
One easy way is to use a pipe as a communication channel between the (worker) threads and your main thread. When a thread terminates it writes its result (thread id in the following example) to the pipe. The main thread waits on the pipe and reads the thread result from it as soon as it becomes available.
Unlike mutex or semaphore, a pipe file descriptor can be easily handled by the application main event loop (such as libevent). The writes from different threads to the same pipe are atomic as long as they write PIPE_BUF or less bytes (4096 on my Linux).
Below is a demo that creates ten threads each of which has a different life span. Then the main thread waits for any thread to terminate and prints its thread id. It terminates when all ten threads have completed.
$ cat test.cc
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
void* thread_fun(void* arg) {
// do something
unsigned delay = rand() % 10;
usleep(delay * 1000000);
// notify termination
int* thread_completed_fd = static_cast<int*>(arg);
pthread_t thread_id = pthread_self();
if(sizeof thread_id != write(*thread_completed_fd, &thread_id, sizeof thread_id))
abort();
return 0;
}
int main() {
int fd[2];
if(pipe(fd))
abort();
enum { THREADS = 10 };
time_t start = time(NULL);
// start threads
for(int n = THREADS; n--;) {
pthread_t thread_id;
if(pthread_create(&thread_id, NULL, thread_fun, fd + 1))
abort();
std::cout << time(NULL) - start << " sec: started thread " << thread_id << '\n';
}
// wait for the threads to finish
for(int n = THREADS; n--;) {
pthread_t thread_id;
if(sizeof thread_id != read(fd[0], &thread_id, sizeof thread_id))
abort();
if(pthread_join(thread_id, NULL)) // detached threads don't need this call
abort();
std::cout << time(NULL) - start << " sec: thread " << thread_id << " has completed\n";
}
close(fd[0]);
close(fd[1]);
}
$ g++ -o test -pthread -Wall -Wextra -march=native test.cc
$ ./test
0 sec: started thread 140672287479552
0 sec: started thread 140672278759168
0 sec: started thread 140672270038784
0 sec: started thread 140672261318400
0 sec: started thread 140672252598016
0 sec: started thread 140672243877632
0 sec: started thread 140672235157248
0 sec: started thread 140672226436864
0 sec: started thread 140672217716480
0 sec: started thread 140672208996096
1 sec: thread 140672208996096 has completed
2 sec: thread 140672226436864 has completed
3 sec: thread 140672287479552 has completed
3 sec: thread 140672243877632 has completed
5 sec: thread 140672252598016 has completed
5 sec: thread 140672261318400 has completed
6 sec: thread 140672278759168 has completed
6 sec: thread 140672235157248 has completed
7 sec: thread 140672270038784 has completed
9 sec: thread 140672217716480 has completed
Related
I'm very new to thread coding, so I was doing an exercise I found out there on the web, which asks for something like this:
Write a program hellomany.c that will create a number N of threads specified in the command line, each of which prints out a hello message and its own thread ID. To see how the execution of the threads interleaves, make the main thread sleep for 1 second for every 4 or 5 threads it creates. The output of your code should be similar to:
I am thread 1. Created new thread (4) in iteration 0...
Hello from thread 4 - I was created in iteration 0
I am thread 1. Created new thread (6) in iteration 1...
I am thread 1. Created new thread (7) in iteration 2...
I am thread 1. Created new thread (8) in iteration 3...
I am thread 1. Created new thread (9) in iteration 4...
I am thread 1. Created new thread (10) in iteration 5...
Hello from thread 6 - I was created in iteration 1
Hello from thread 7 - I was created in iteration 2
Hello from thread 8 - I was created in iteration 3
Hello from thread 9 - I was created in iteration 4
Hello from thread 10 - I was created in iteration 5
I am thread 1. Created new thread (11) in iteration 6...
I am thread 1. Created new thread (12) in iteration 7...
Hello from thread 11 - I was created in iteration 6
Hello from thread 12 - I was created in iteration 7
What I've managed to code is this:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* PrintHello(int iteration)
{
printf("Hello from thread %u - I was created in iteration %d \n",
pthread_self(), iteration);
pthread_exit(NULL);
}
int main(void)
{
int rc;
pthread_t thread_id;
int tidMain;
int n, i;
tidMain = pthread_self();
printf("How many threads are there to be created?\n");
scanf("%d", &n);
for(i = 1; i <= n; i++) {
pthread_t thread_id;
rc = pthread_create(&thread_id, NULL, PrintHello, i);
printf("I am thread %u. Created new thread (%u) in iteration %d\n",
tidMain, thread_id, i);
if(rc)
{
printf("\n ERROR: return code from pthread_create is %d \n", rc);
exit(1);
}
if((i % 5) == 0) {
sleep(1);
}
}
pthread_exit(NULL);
}
The program does really print what I want to, and even sleeps and "breaks" the creation each 5 threads created; still, I don't know why, but when each created thread gets to be executed (after main thread has informed they have been created) in the 5-thread-printing-streak i want to, first thread that "greets" is the last created one. What i get from the console, i.e. when I ask it to create 8 threads, is this:
I am thread 3075630848. Created new thread (3075627840) in iteration 1
I am thread 3075630848. Created new thread (3067235136) in iteration 2
I am thread 3075630848. Created new thread (3058842432) in iteration 3
I am thread 3075630848. Created new thread (3050449728) in iteration 4
I am thread 3075630848. Created new thread (3042057024) in iteration 5
Hello from thread 3042057024 - I was created in iteration 5
Hello from thread 3050449728 - I was created in iteration 4
Hello from thread 3058842432 - I was created in iteration 3
Hello from thread 3067235136 - I was created in iteration 2
Hello from thread 3075627840 - I was created in iteration 1
I am thread 3075630848. Created new thread (3032480576) in iteration 6
I am thread 3075630848. Created new thread (3024087872) in iteration 7
I am thread 3075630848. Created new thread (3015695168) in iteration 8
Hello from thread 3015695168 - I was created in iteration 8
Hello from thread 3024087872 - I was created in iteration 7
Hello from thread 3032480576 - I was created in iteration 6
As long as I understand, it is first executing the last thread created. Why does this happen? Can I get it to execute the first created one first?
BTW: I'm running on Ubuntu
This is the point about concurrent programming. You can never make any assumptions about the order in which the threads execute. I, for example get the following output:
I am thread 639280960. Created new thread (630781696) in iteration 1
Hello from thread 630781696 - I was created in iteration 1
I am thread 639280960. Created new thread (622388992) in iteration 2
Hello from thread 622388992 - I was created in iteration 2
I am thread 639280960. Created new thread (613996288) in iteration 3
Hello from thread 613996288 - I was created in iteration 3
I am thread 639280960. Created new thread (536868608) in iteration 4
Hello from thread 536868608 - I was created in iteration 4
I am thread 639280960. Created new thread (526280448) in iteration 5
Hello from thread 526280448 - I was created in iteration 5
I am thread 639280960. Created new thread (517887744) in iteration 6
I am thread 639280960. Created new thread (509495040) in iteration 7
Hello from thread 509495040 - I was created in iteration 7
I am thread 639280960. Created new thread (501102336) in iteration 8
Hello from thread 501102336 - I was created in iteration 8
Hello from thread 517887744 - I was created in iteration 6
If I run it again, I might get a different output. Try it out on your own!
The Wikipedia Article about Concurrent computing, says the following:
The exact timing of when tasks in a concurrent system are executed
depend on the scheduling, and tasks need not always be executed
concurrently. For example, given two tasks, T1 and T2:
T1 may be executed and finished before T2 or vice versa (serial and sequential)
T1 and T2 may be executed alternately (serial and concurrent)
T1 and T2 may be executed simultaneously at the same instant of time (parallel and concurrent)
I suggest, you read some basic articles or literature about concurrency and parallelism.
It's a concurrent program. If you run your program several times, the order may be different even in the same host.
By the way, maybe it is better for you to see pthread API first before coding.
For pthread_create():
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
The 3rd argument is void *(*start_routine)(void *) rather than void *(start_routine)(int), and the 4th argument is void * rather than int.
The order in which threads are executed is undetermined. If you need a specific order than you have to use locks, mutexes and conditions to order their executuion to your requirements.
The order that you see is caused by your hardware and kernel and sometimes randomness. I'm assuming you have a single core cpu or the output would make little sense. When you create a thread your kernel simply schedules the thread to run at a later time and keeps executing the main thread. So you get messages for all 5 thread creations. Only when the main thread sleeps the kernel switches to the next thread ready to run. It seems to do this as FILO (first in - last out). That just happens to be what your kernel in your version on your hardware happens to do. Could change at any moment.
pOwl on the other hand seems to have multiple cores. So while the main thread creates thread the other core(s) already execute them. Or he simply has a different kernel.
this is my first pthread program, and I have no idea why the printf statement get printed twice in child thread:
int x = 1;
void *func(void *p)
{
x = x + 1;
printf("tid %ld: x is %d\n", pthread_self(), x);
return NULL;
}
int main(void)
{
pthread_t tid;
pthread_create(&tid, NULL, func, NULL);
printf("main thread: %ld\n", pthread_self());
func(NULL);
}
Observed output on my platform (Linux 3.2.0-32-generic #51-Ubuntu SMP x86_64 GNU/Linux):
1.
main thread: 140144423188224
tid 140144423188224: x is 2
2.
main thread: 140144423188224
tid 140144423188224: x is 3
3.
main thread: 139716926285568
tid 139716926285568: x is 2
tid 139716918028032: x is 3
tid 139716918028032: x is 3
4.
main thread: 139923881056000
tid 139923881056000: x is 3
tid 139923872798464tid 139923872798464: x is 2
for 3, two output lines from the child thread
for 4, the same as 3, and even the outputs are interleaved.
Threading generally occurs by time-division multiplexing. It is generally in-efficient for the processor to switch evenly between two threads, as this requires more effort and higher context switching. Typically what you'll find is a thread will execute several times before switching (as is the case with examples 3 and 4. The child thread executes more than once before it is finally terminated (because the main thread exited).
Example 2: I don't know why x is increased by the child thread while there is no output.
Consider this. Main thread executes. it calls the pthread and a new thread is created.The new child thread increments x. Before the child thread is able to complete the printf statement the main thread kicks in. All of a sudden it also increments x. The main thread is however also able to run the printf statement. Suddenly x is now equal to 3.
The main thread now terminates (also causing the child 3 to exit).
This is likely what happened in your case for example 2.
Examples 3 clearly shows that the variable x has been corrupted due to inefficient locking and stack data corruption!!
For more info on what a thread is.
Link 1 - Additional info about threading
Link 2 - Additional info about threading
Also what you'll find is that because you are using the global variable of x, access to this variable is shared amongst the threads. This is bad.. VERY VERY bad as threads accessing the same variable create race conditions and data corruption due to multiple read writes occurring on the same register for the variable x.
It is for this reason that mutexes are used which essentially create a lock whilst variables are being updated to prevent multiple threads attempting to modify the same variable at the same time.
Mutex locks will ensure that x is updated sequentially and not sporadically as in your case.
See this link for more about Pthreads in General and Mutex locking examples.
Pthreads and Mutex variables
Cheers,
Peter
Hmm. your example uses the same "resources" from different threads. One resource is the variable x, the other one is the stdout-file. So you should use mutexes as shown down here. Also a pthread_join at the end waits for the other thread to finish its job. (Usually a good idea would also be to check the return-codes of all these pthread... calls)
#include <pthread.h>
#include <stdio.h>
int x = 1;
pthread_mutex_t mutex;
void *func(void *p)
{
pthread_mutex_lock (&mutex);
x = x + 1;
printf("tid %ld: x is %d\n", pthread_self(), x);
pthread_mutex_unlock (&mutex);
return NULL;
}
int main(void)
{
pthread_mutex_init(&mutex, 0);
pthread_t tid;
pthread_create(&tid, NULL, func, NULL);
pthread_mutex_lock (&mutex);
printf("main thread: %ld\n", pthread_self());
pthread_mutex_unlock (&mutex);
func(NULL);
pthread_join (tid, 0);
}
It looks like the real answer is Michael Burr's comment which references this glibc bug: https://sourceware.org/bugzilla/show_bug.cgi?id=14697
In summary, glibc does not handle the stdio buffers correctly during program exit.
Here is what I am trying to do:
Start 10 posix threads from the main thread.
Each of the 10 threads will do some operation say 100 times.
This is what I need help with.
I want to allow thread_1 to do its thing for say 10 seconds (while threads 2-10 are suspended) and then I want to allow thread 2 to do its thing while thread 1 and threads 3-10 are suspended and so on.
How would I do that? I was looking at some pthread tutorials but things seemed complicated even though what I am trying to do is quite straightforward.
Besides any discussion on whether the OP's question makes sense or not, a possible solution could be the following:
Have a signal handler installed for each thread to be scheduled. This handler is triggered on say SIGUSR1 and internally does nothing more than to invoked a call to pause().
The thread functions all start with a call to pause(), which suspends all threads immediatly after creation.
Create all threads to be schedules using pthread_create(). Stores the pthreads created into an array pthreads.
Assign the first pthread to be run (from pthread) to pthread_first.
To start scheduling call pthread_kill(pthread_first, SIGUSR2) to resume the thread to be run first (by makeing the pause() its blocking on to return). Make pthread_current become pthread_first.
To actually perform scheduling an additional thread (perhaps the main thread) loops infinitly and calls sleep(SCHEDULING_INTERVALL) and then calls pthread_kill(pthread_current, SIGUSR1) to suspend the current thread (by invoking its signal handler and with this running into pause()). Then call pthread_kill(pthread_next, SIGUSR2) to resume the next thread (by makeing the pause() its blocking on to return). Make pthreat_current become pthread_next, and pthread_next become another entry from the array pthread filled during thread creation.
But be aware:
As the threads interupted by signals and suspended by pause() might have been caught in the middle of doing some work on shared resources and stay their until resumed the chances of stepping on each other toes are quiet high.
To all others: yes, beat me ;-)
Update:
Equivalent example:
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#define THREADSMAX (3)
#define SCHEDULING_INTERVALL (5) /* seconds */
void
sigusr_handler(int signo)
{
if (SIGUSR1 == signo)
{
pause();
}
}
void *
thread_function(void * pv)
{
intptr_t iThread = (intptr_t) pv;
pause();
{
int i = 0;
for (;;)
{
printf("%d: %d\n", (int) iThread, i++);
sleep(1);
}
}
pthread_exit(NULL);
}
int
main(int argc, char ** argv)
{
struct sigaction signal_action;
memset(&signal_action, 0, sizeof(signal_action));
signal_action.sa_handler = sigusr_handler;
sigemptyset(&signal_action.sa_mask);
sigaction(SIGUSR1, &signal_action, NULL);
sigaction(SIGUSR2, &signal_action, NULL);
{
pthread_t threads[THREADSMAX] =
{ 0 };
intptr_t iThread = 0;
/* create threads */
for (; iThread < THREADSMAX; ++iThread)
{
int iResult = pthread_create(&threads[iThread], NULL, thread_function,
(void *) iThread);
if (iResult)
{
errno = iResult;
perror("pthread_created()");
exit(1);
}
}
sleep(1); /* Unreliable workaround: Try to make sure all threads have started and block in "pause()". See comments on how this might be fixed nicely ... */
/* scheduling loop */
for (iThread = 0;; ++iThread)
{
if (THREADSMAX == iThread)
{
iThread = 0;
}
/* Resume current thread */
{
int iResult = pthread_kill(threads[iThread], SIGUSR2);
if (iResult)
{
errno = iResult;
perror("pthread_kill(..., SIGUSR2)");
exit(2);
}
}
sleep(SCHEDULING_INTERVALL);
/* Suspend current thread */
{
int iResult = pthread_kill(threads[iThread], SIGUSR1);
if (iResult)
{
errno = iResult;
perror("pthread_kill(..., SIGUSR1)");
exit(3);
}
}
}
}
return 0;
}
Expected output:
0: 0
0: 1
0: 2
0: 3
0: 4
1: 0
1: 1
1: 2
1: 3
1: 4
2: 0
2: 1
2: 2
2: 3
2: 4
0: 5
0: 6
0: 7
0: 8
0: 9
1: 5
1: 6
1: 7
1: 8
1: 9
2: 5
2: 6
...
POSIX Threads: Condition Variables - what's the point?
Joining and Detaching Threads:
Using sleep() and the scheduler will context switch to another process. IMO it isn't so bad solution - it is not generic since in some scenario 100ms is a lot of time and on another it is very short.
Implement by ourself condition variables or some sort of synchronizer- but it is really isn't recommended.
You have not stated your requirements well. Do the threads all operate on independent data (with no need for synchronization between them)? If so, the whole idea of trying to do your own course scheduling in 10-second units is nonsensical. Just let them all run and do their thing. Of course it would be fairly easy to achieve what you asked for using timer signals and controlling which threads have the signal blocked, but it would also be utterly useless.
If on the other hand your threads do have data dependencies between one another, then any pattern of "run for 10 seconds then transfer control to another thread" is invalid; it could lead to deadlock if the next thread cannot proceed because of a lock the first thread holds. (I suppose it's not entirely dead-lock since control will eventually return to the first thread, but the delays could grow on a very large order if there are multiple locks involved.) Instead, in this case, you should be aiming to have which thread is running controlled by the flow of data.
I am new to multithreading in C and I had this question. I wrote the following code:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER;
pthread_attr_t attr;
void* test(void *a)
{
int i=*((int *)a);
printf("The thread %d has started.\n",i);
pthread_mutex_lock(&m);
sleep(1);
printf("The thread %d has finished.\n",i);
pthread_mutex_unlock(&m);
pthread_exit(NULL);
}
int main()
{
int i=0;
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
pthread_t thread[5];
for (i=0;i<5;i++)
pthread_create(&thread[i],&attr,test,&i);
for (i=0;i<5;i++)
pthread_join(thread[i],NULL);
return 0;
}
Why do I get values like:
The thread 0 has started.
The thread 0 has started.
The thread 5 has started.
The thread 5 has started.
The thread 0 has started.
The thread 0 has finished.
The thread 0 has finished.
The thread 5 has finished.
The thread 5 has finished.
The thread 0 has finished.
or
The thread 1 has started.
The thread 2 has started.
The thread 5 has started.
The thread 4 has started.
The thread 0 has started.
The thread 1 has finished.
The thread 2 has finished.
The thread 5 has finished.
The thread 4 has finished.
The thread 0 has finished.
or even:
The thread 0 has started.
The thread 0 has started.
The thread 0 has started.
The thread 0 has started.
The thread 0 has started.
The thread 0 has finished.
The thread 0 has finished.
The thread 0 has finished.
The thread 0 has finished.
The thread 0 has finished.
etc, when I expected to get:
The thread 0 has started.
The thread 1 has started.
The thread 2 has started.
The thread 3 has started.
The thread 4 has started.
The thread 0 has finished.
The thread 1 has finished.
The thread 2 has finished.
The thread 3 has finished.
The thread 4 has finished.
Only when I put usleep(10) after thread_create do I get some "normal" values.
I compiled and run this code in Code::Blocks on Unix.
You're passing the address of a variable the for is changing (i) so you're at the mercy of the scheduler. You should just pass a copy. As a cheap, not completely-kosher way:
pthread_create(&thread[i],&attr,test, (void*)i);
/* ... */
int i = (int)a;
Notice that you are passing in the address of i as a parameter to your threads:
pthread_create(&thread[i],&attr,test,&i);
This means that all of your threads will be reading the same variable i to determine which thread they are. That is, all five threads will look at the same variable to determine their thread number. Consequently, as the value of i increments in your for loop, all the threads will perceive their thread number changing to use the new value of i. This is why you're sometimes seeing 5 come up as the thread number, and also explains the fact that you're often skipping numbers or seeing far too many duplicates.
To fix this, you will need to give each thread their own copy of i. For example, you could do something like this:
int* myI = malloc(sizeof(int));
*myI = i;
pthread_create(&thread[i], &attr, test, myI);
And then have the threads free the pointer before terminating:
void* test(void *a)
{
int i=*((int *)a);
printf("The thread %d has started.\n",i);
pthread_mutex_lock(&m);
sleep(1);
printf("The thread %d has finished.\n",i);
pthread_mutex_unlock(&m);
pthread_exit(NULL);
free(a);
}
Alternatively, you could cast i to a void* and pass that in:
pthread_create(&thread[i],&attr,test, (void*)i);
If you do this, you would then have the threads cast their arguments directly back to int, not to int*:
void* test(void *a)
{
int i = (int)a;
printf("The thread %d has started.\n",i);
pthread_mutex_lock(&m);
sleep(1);
printf("The thread %d has finished.\n",i);
pthread_mutex_unlock(&m);
pthread_exit(NULL);
}
Hope this helps!
I'm trying to develop a program to time limit the execution of a function. In the code below I have a function named Inc which does a lot of iterations (simulated by the infinite loop). The first part of each iteration is quite long, followed by a second part that should be pretty fast.
I don't mind preempting the execution while in the first part of the code, but I'd like to avoid the alarm going off while doing a write operation on the second part.
My first idea was to turn off the alarm before entering the 'safe region' saving the remaining time. Then after exiting, I would set the alarm up with the saved time. I don't know how to implement this. Could someone help me? Alternative methods are also welcome.
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_t thread;
FILE *fout;
void *Inc(void *param){
int i;
long long int x = 0;
fout = fopen("file.txt", "w");
/* Large number of iterations */
while(1){
int k = 0;
for(i=0; i<5000000; i++)
k += (rand())%3;
x += k;
printf("%lld\n", x);
/* Enter Safe Region */
fprintf(fout, "%lld\n", x);
/* Exit Safe Region */
}
}
void Finish(int param){
pthread_cancel(thread);
fclose(fout);
}
main (){
pthread_attr_t attr;
void *status;
signal(SIGALRM, Finish);
alarm(10);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&thread, &attr, Inc, NULL);
pthread_attr_destroy(&attr);
pthread_join(thread, &status);
printf("Program Finished\n");
}
The obvious thing is to take a lock before calling pthread_cancel, and to hold the same lock across your "safe region".
Unfortunately, you can't wait on a mutex or a semaphore in a signal handler. But alarm signals aren't the only way to do something after 10 seconds - you could instead have your main thread go to sleep for 10 seconds, then wake up, take the lock, cancel the worker thread and then join it.
Of course this would mean that the main thread will sleep 10 seconds even if the worker thread finishes after 5 seconds. So instead of sleeping, have the main thread do a 10 second timed wait on a semaphore, which the worker thread posts when it finishes.
Like a sleep, a timed wait can complete early due to a signal, so be sure to retry the timed wait on EINTR. Your significant cases are EINTR (wait again), success (join the worker thread - no need to cancel since it has posted the semaphore), ETIMEDOUT (take the lock, cancel, join) and if you like, other errors. There are no other errors listed for sem_timedwait that should affect you, though.
Another idea is to block SIGALRM across your "safe region", which would be simpler except that (a) I can never remember how to safely do I/O with signals disabled, and (b) your worker thread could probably be running "simultaneously" with the signal handler (either truly simultaneous or apparently so due to pre-emption), meaning that the signal could be taken, then your worker disables signals and enters the critical region, then the signal handler cancels it. If nobody answers who can actually remember the details, here's some information on blocking signals.