c++linuxsignalssemaphoresigbus

sem_wait() triggers a SIGBUS exception


I have a C++ Linux commandline application, which does a bunch of things and then closes by itself. I am blocking the main thread using a semaphore and when the background thread completes its activity, it unlocks the semaphore, releasing the main thread, which returns from int main().

// Static definition of the semaphore object. This semaphore object is 
// declared as a static array of 32 bytes in class A
uint8_t  A::semaphore[sizeof(sem_t)];
-----------------------------------------------------------------------

// In int main()
if(sem_init ((sem_t *) A::semaphore, 0, 0)) {
    // failed to initialize semaphore
}

printf("semaphore = %p\n", A::semaphore);  // Prints 0x129ba01

// Create another thread(s) to execute work

// Main thread gets blocked here... until thread(s) complete their work.
sem_wait ((sem_t *) A::semaphore);

// Once main thread gets unblocked, return from int main() with return value

I've also attached my own exception handler using sigaction. It turns out that, when main thread reaches sem_wait, my exception handler gets invoked with the signal number value of 7, which is a SIGBUS exception. I've also printed additional details using siginfo_t object passed to the exception handler.

// Exception handler belonging to Class B
void B::handleException(int32_t signum, siginfo_t * info, void * context) noexcept
{
    printf("signo = %d\n", info->si_signo); // Prints 7
    printf("errno = %d\n", info->si_errno);
    printf("code = %d\n", info->si_code);
    printf("si_addr = %p\n", info->si_addr); // Prints 0x129ba01


    ....
}

As shown above, the caught exception is SIGBUS and the si_addr property of siginfo - which points to the memory location of the fault, prints the address of the semaphore. Then, the signal documentation states the following for SIGBUS:

For example, an invalid memory access that causes delivery of SIGSEGV on one CPU architecture may cause delivery of SIGBUS on another architecture, or vice versa.

I think what I'm really getting is a SIGSEGV exception... and there is some memory access violation... but I'm not able to find it.

What am I missing here?

Note: SIGBUS gets thrown only on Linux arm64. My app works fine on Linux x64.


Solution

  • You're stuffing your sem_t into a byte array, which has no alignment requirements, but sem_t almost certainly does. So when you go to actually use it, you get an error from accessing unaligned memory.

    You should be using a sem_t if you want a sem_t. Or just use the threading and IPC primitives that have been in C++ for a while now.