Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

icpc pthread_cancel raises exception in C++ program

gn164
Beginner
1,413 Views

 

Hi,

The following piece of code shows a scenario where the main thread calls pthread_cancel on a background thread that is sleeping.

The sleeping thread would then raise an abort signal that would cause the application to terminate abnormally.

#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <string.h>

using namespace std;

struct ToBeDestroyed
{
   ~ToBeDestroyed()
    {
       cout << "destructor called" << endl ;
    }
};

static void * thread_func(void *ignored_argument)
{
   ToBeDestroyed d;
   sleep(100000);        /* Should get canceled while we sleep */
   return NULL;
}

int main(void)
{
   pthread_t thr;
   void *res;
   int s;

   /* Start a thread and then send it a cancellation request */
   s = pthread_create(&thr, NULL, &thread_func, NULL);

   printf("main(): about to send cancellation request in 5 sec ...\n");

   sleep(5);           /* Give thread a chance to get started */

   printf("main(): sending cancellation request\n");

   s = pthread_cancel(thr);

   s = pthread_join(thr, &res);

  exit(EXIT_SUCCESS);
}

 

The abort stack looks like the following:

 

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff6fb442a in __GI_abort () at abort.c:89
#2  0x00007ffff7ae80ad in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff7ae6066 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff7ae60b1 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff7ae5cd4 in __gxx_personality_v0 () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff754c009 in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#7  0x00007ffff754c364 in _Unwind_ForcedUnwind () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#8  0x00007ffff732ed60 in __GI___pthread_unwind (buf=<optimized out>) at unwind.c:121
#9  0x00007ffff7324c5a in __do_cancel () at ./pthreadP.h:283
#10 sigcancel_handler (sig=<optimized out>, si=0x7ffff6d7aa70, ctx=<optimized out>) at nptl-init.c:220
#11 <signal handler called>
#12 0x00007ffff703828d in nanosleep () at ../sysdeps/unix/syscall-template.S:84
#13 0x00007ffff70381da in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
#14 0x00000000004011cb in _INTERNAL9b371893::thread_func(void*) ()
#15 0x00007ffff7326494 in start_thread (arg=0x7ffff6d7b700) at pthread_create.c:333
#16 0x00007ffff7068acf in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:97

 

The exception seems to be caused by the existence a local object on the thread stack that would need to have its destructors called.

If there is no local object on the thread stack the program terminates normally and no abort signal is raised.

Compilation command:

icpc test_pthreadsn.cpp -pthread
icpc version 18.0.2

The same code runs fine when compiled with gcc  6.3.0

Could someone please share some thoughts why this is happening and if it is inherent to the compiler.

 

0 Kudos
5 Replies
Viet_H_Intel
Moderator
1,414 Views

 

Let me investigate this problem and get back to you.

Thanks,

Viet

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,413 Views

Google: pthread_cancel vs pthread_join

The pthread_cancel() function sends a cancellation request to the thread thread. Whether and when the target thread reacts to the cancellation request depends on two attributes that are under the control of that thread: its cancelability state and type.

A thread's cancelability state, determined by pthread_setcancelstate(3), can be enabled (the default for new threads) or disabled. If a thread has disabled cancellation, then a cancellation request remains queued until the thread enables cancellation. If a thread has enabled cancellation, then its cancelability type determines when cancellation occurs.

A thread's cancellation type, determined by pthread_setcanceltype(3), may be either asynchronous or deferred (the default for new threads). Asynchronous cancelability means that the thread can be canceled at any time (usually immediately, but the system does not guarantee this). Deferred cancelability means that cancellation will be delayed until the thread next calls a function that is a cancellation point. A list of functions that are or may be cancellation points is provided in pthreads(7).

When a cancellation requested is acted on, the following steps occur for thread (in this order):

1.
Cancellation clean-up handlers are popped (in the reverse of the order in which they were pushed) and called. (See pthread_cleanup_push(3).)
2.
Thread-specific data destructors are called, in an unspecified order. (See pthread_key_create(3).)
3.
The thread is terminated. (See pthread_exit(3).)

The above steps happen asynchronously with respect to the pthread_cancel() call; the return status of pthread_cancel() merely informs the caller whether the cancellation request was successfully queued.

After a canceled thread has terminated, a join with that thread using pthread_join(3) obtains PTHREAD_CANCELED as the thread's exit status. (Joining with a thread is the only way to know that cancellation has completed.)  

RETURN VALUE

On success, pthread_cancel() returns 0; on error, it returns a nonzero error number.  

Jim Dempsey

0 Kudos
Viet_H_Intel
Moderator
1,413 Views

 

This seems to be a compiler bug. I filed a bug report CMPLRIL0-30574.

Thanks,

Viet

0 Kudos
gn164
Beginner
1,413 Views

Hi Viet,

Do you know if this has been fixed in any newer icpc version.

 

0 Kudos
That__Tam
Beginner
1,414 Views

I have also encountered this problem tam that bac . C++

0 Kudos
Reply