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

icc12 causing pthread failures?

bsteintrc
Beginner
490 Views
Hi.

I compiled the following code with icc12 and it aborts at run-time when pthread_exit tries to unwind the stack. The cause, as I understand it, is due to an empty call site table generated by icc12. In contrast, icc11.1 generates a proper table.

My compilation flags are -O2 -pthread, my code is

#include
#include

int counter;

class Guard {
public:
Guard() {
++counter;
}
~Guard() {
--counter;
}
};

void *handler_with_guard(void *)
{
Guard l;
pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
pthread_t t;
int result = pthread_create(&t, 0, handler_with_guard, 0);
printf("pthread_create result = %d\\n", result);

result = pthread_join(t, NULL);
printf("pthread_join result = %d\\n", result);
printf("counter = %d\\n", counter);

return 0;
}

The generated .gcc_except_table by icc12 is

.section .gcc_except_table, "a"
.align 4
_Z18handler_with_guardPv$$LSDA:
.byte 255
.byte 0
.uleb128 ..___tag_value__Z18handler_with_guardPv.24 - ..___tag_value__Z18handler_with_guardPv.23
..___tag_value__Z18handler_with_guardPv.23:
.byte 1
.uleb128 ..___tag_value__Z18handler_with_guardPv.22 - ..___tag_value__Z18handler_with_guardPv.21
..___tag_value__Z18handler_with_guardPv.21:
..___tag_value__Z18handler_with_guardPv.22:
.long 0x00000000,0x00000000
..___tag_value__Z18handler_with_guardPv.24:

The list of arguments to the icc are:
mcpcom -_g -mP3OPT_inline_alloca -D__HONOR_STD -D__ICC=1200 -D__INTEL_COMPILER=1200 -D_MT "-_Asystem(unix)" -D__ELF__ "-_Acpu(x86_64)" "-_Amachine(x86_64)" -D__INTEL_COMPILER_BUILD_DATE=20101116 -D__PTRDIFF_TYPE__=long "-D__SIZE_TYPE__=unsigned long" -D__WCHAR_TYPE__=int "-D__WINT_TYPE__=unsigned int" "-D__INTMAX_TYPE__=long int" "-D__UINTMAX_TYPE__=long unsigned int" -D__LONG_MAX__=9223372036854775807L -D__QMSPP_ -D_REENTRANT -D__OPTIMIZE__ -D__NO_MATH_INLINES -D__NO_STRING_INLINES -D__GNUG__=3 -D__GNUC__=3 -D__GNUC_MINOR__=4 -D__GNUC_PATCHLEVEL__=6 -D__NO_INLINE__ -D__i686 -D__i686__ -D__pentiumpro -D__pentiumpro__ -D__pentium4 -D__pentium4__ -D__tune_pentium4__ -D__MMX__ -D__LP64__ -D_LP64 -D_GNU_SOURCE=1 -D__DEPRECATED=1 -D__GXX_WEAK__=1 -D__GXX_ABI_VERSION=1002 "-D__USER_LABEL_PREFIX__= " -D__REGISTER_PREFIX__= -D__INTEL_RTTI__ -D__EXCEPTIONS=1 -D__SSE2__ -D__SSE__ -D__unix__ -D__unix -D__linux__ -D__linux -D__gnu_linux__ -B -Dunix -Dlinux -D__x86_64 -D__x86_64__ -_k -_8 -_l -_a -_b --gnu_version=346 -mGLOB_gcc_version=346 -_W5 --gcc-extern-inline -p --bool -tused -mGLOB_eh_linux -x --multibyte_chars --array_section --simd --simd_func --bool -mP1OPT_version=12.0-intel64 -mGLOB_diag_file=scopetest.diag -mP1OPT_print_version=FALSE -mCG_use_gas_got_workaround=F -mP2OPT_align_option_used=TRUE "-mGLOB_options_string=-O2 -pthread -S -v" -mGLOB_cxx_limited_range=FALSE -mIPOPT_activate -mIPOPT_lite -mGLOB_machine_model=GLOB_MACHINE_MODEL_EFI2 -mGLOB_product_id_code=0x22001de3 -mGLOB_extended_instructions=0x8 -mP3OPT_use_mspp_call_convention -mPGOPTI_value_profile_use=T -mP2OPT_il0_array_sections=TRUE -mGLOB_opt_level=2 -mP2OPT_hlo_level=2 -mP2OPT_hlo -mP2OPT_hpo_rtt_control=0 -mIPOPT_args_in_regs=0 -mIPOPT_obj_output_file_name=scopetest.o -mGLOB_linker_version=2.20 -mGLOB_long_size_64 -mGLOB_routine_pointer_size_64 -mP3OPT_asm_target=P3OPT_ASM_TARGET_GAS -mP3OPT_emit_asm_debug_info=1 -mGLOB_as_output_file=scopetest.s -mGLOB_source_dialect=GLOB_SOURCE_DIALECT_C_PLUS_PLUS -mP1OPT_source_file_name=scopetest.cpp scopetest.cpp
0 Kudos
8 Replies
jimdempseyatthecove
Honored Contributor III
490 Views
What happens when you initialize counter?

int counter = 0; // add " = 0"

In your posted code, counter is incremented (++) without initialization. The optimizer may have been tripped up by this.

Jim Dempsey
0 Kudos
bsteintrc
Beginner
490 Views
It's my understanding that since it's a global counter, it should be 0 initialized (certainlly in C++ but even in C).
But, on the off chance that it wasn't, I tried adding the =0, and it made no difference.

After doing a bit more digging, it looks like the issue is cornered to extern "C". Icc12 assumes that everything declared as extern "C" will not trigger exception, so skipped in generating the call site entry for code that calls them.
0 Kudos
Om_S_Intel
Employee
490 Views
I think there is bug in intel compiler.

I have submitted a report to intel compiler development team on this. I update this thread when I have more information.

You may use -O0 compiler option as a work arround for now.

0 Kudos
jimdempseyatthecove
Honored Contributor III
490 Views
I assume you extern "C"'d the thread function entry point.

extern "C" void *handler_with_guard(void *)
{
...


0 Kudos
bsteintrc
Beginner
490 Views
Om. Thanks very much. I look forward to your update.
Sadly, -O0 doesn't work for us, since we need the compiler optimizations in the rest of our code, as it's a production system. Fortunately, we were able to find an alternative workaround:
if we write a trivial c++ wrapper for the functions, without inline or throw(), it seems icc decides it might generate an exception, and then everything works properly.

@jimdempseyatthecove - Yes, that's already been tried, and no, it doesn't make a difference. The issue is with pthread_exit, and will occur even if handler_with_guard is not the thread entry point.
0 Kudos
bsteintrc
Beginner
490 Views
Any further updates, here?

Thanks.
0 Kudos
jimdempseyatthecove
Honored Contributor III
490 Views
This may or may not be a related problem. I have been working on some code on Intel 64 that contains __asm blocks. In release mode the code failed. I noticed that the optimizaton defaulted to IPO enabled. So I thought that there may be a problem with the inlining of a function containing the __asm block. As a guess to the problem I added __declspec(noinline) the the function declaration and the resultant code worked as expected. I know your code does not have an __asm block, However, your code has an unusual exit from the called function (it exits the pthread thread). Try adding __declspec(noinline) the the function declaration.

Do notassume -noinline is equivilent to __declspec(noinline) as IPO may be overly aggressive.

Jim Dempsey
0 Kudos
Om_S_Intel
Employee
490 Views
The issue has been resolved in latest Intel compiler 12.0. The compiler is available for download form https://registrationcenter.intel.com/.

Om
0 Kudos
Reply