Search code examples
debuggingpthreadsembedded-linuxqemuarm64

pthread_mutex_init failed while using qemu aarch-64


I tried to emulate aarch64 binary using qemu , I copy all the libraries that this binary depend on. and run it with chroot :

chroot . ./qemu-aarch64-static ./myProcess

The problem is that I see in log that pthread_mutex_init (implement in so file ) failed

How can I check why pthread_mutex_init failed? can I see the errno?

I have tried to debug that process ` maybe to see the return value of that function but it doesn't work.

Using chroot . ./qemu-aarch64-static -g 1234 ./myProcess

then connect with gdb-multiarch

file myProcess
set architecture aarch64
target remote 127.0.0.1:1234
b main
c

But the process doesn't stop at main

So I don't know why pthread_mutex_init failed and why I can't debug that process.


Solution

  • How can I check why pthread_mutex_init failed? can I see the errno?

    The pthreads functions are among those that return an error number on failure rather than setting the errno variable.

    As with any function call whose failure you cannot reasonably ignore, your program must check calls to pthread_mutex_init for failure. The natural idiom is

        int result;
    
        // ...
    
        result = pthread_mutex_init(&my_mutex, NULL);  // assumes default mutex attributes
        if (result != 0) {
            // ... handle error ...
        }
    

    That idiom is already sufficient for easily seeing the error number via a debugger, at least a native debugger. I'm not sure I can explain the behavior you report for gdb-multiarch, but I suspect that the issue is that you're connecting after the program has started, but trying to break at (entry into) main.

    The question remains, though, how do you actually handle the error. In some cases, you might want to print a diagnostic message. The perror() function is reasonably good for this, but it uses errno to determine what message to emit, so maybe ...

            errno = result;
            perror("pthread_mutex_init");
    

    Messaging alone is rarely sufficient, however. In most cases you will want to follow that up with terminating the program or aborting the function with a failure code.

    Note also that for robustness and predictability, a program typically needs to do a lot of error checks along those lines. You may find it makes your code cleaner and clearer to provide one or more macros and / or functions to replace all the boilerplate error handling.