https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66631
--- Comment #3 from Stas Sergeev <stsp at users dot sourceforge.net> --- The signal handler needs to do the following things: 1. Restore segment registers (init_handler() func) 2. Increment thread-local var (fault_cnt) 3. Do stuff including reads of fault_cnt var Being thread-local, fault_cnt var is being accessed with the help of FS, but FS is only valid after the call to init_handler(). Since fault_cnt is marked as volatile, gcc does not move the access to it above the init_handler() call, so that part is fine. What is NOT fine is this: 0x00000000004438d4 <+20>: mov %fs:0x0,%rbp <-- (bad) TLS access 0x00000000004438dd <+29>: push %rbx 0x00000000004438de <+30>: add $0xffffffffffffff80,%rsp 0x00000000004438e2 <+34>: callq 0x4441b0 <init_handler> <-- FS now valid 0x00000000004438e7 <+39>: mov 0x35070a(%rip),%rbx # 0x793ff8 0x00000000004438ee <+46>: mov 0x0(%rbp,%rbx,1),%eax <-- STACK FAULT As you can see, gcc moved some TLS access above init_handler(), which results in a stack fault later when trying to read from fault_cnt. To prevent moving any TLS access around init_handler(), I need to do the following: asm volatile("":::"fs"); but this gives a compilation error. Is the explanation clear?