androidc++multithreadingmutex

Possible Thread Starvation in C++


I have a decode function that decodes a string and internally uses a map to store already-decoded values for efficiency. This function is accessed by multiple threads (using pthread), so to prevent concurrent access issues with the map, I added a std::mutex. However, after adding the mutex, I noticed that some threads eventually stop working or appear to get stuck. When I removed the mutex locks, all threads ran without any issues.

My question is: Could this be a case of starvation? How can I resolve this?

Additional Context: This C++ code is being used in an Android application via JNI.

std::unordered_map<std::string, std::pair<int, std::vector<uint8_t>>> decoded_map;
std::mutex decoded_map_mutex;

const char* decode(const char* encodedString) {
    std::string encoded(encodedString);
    std::string decoded;
    
    for (/* some condition */) {
        {
            std::lock_guard<std::mutex> lock(decoded_map_mutex);
            // Operation involving map search
            auto it = decoded_map.find(part);
            if (it != decoded_map.end()) {
                // Some processing
            }
        }
        // Additional processing
        {
            std::lock_guard<std::mutex> lock(decoded_map_mutex);
            decoded_map[part] = std::make_pair(index / 4, bytes);
        }
        
        decode += part;
    }

    return strdup(decoded.c_str());
}

Solution

  • Do not call fork from a program that has more than one live thread. The Android OS is based on the Linux kernel, and the man 2 fork page from Linux says this:

       •  The child process is created with a single thread—the one that
          called fork().  The entire virtual address space of the parent
          is replicated in the child, including the states of mutexes,
          condition variables, and other pthreads objects; the use of
          pthread_atfork(3) may be helpful for dealing with problems
          that this can cause.
    
       •  After a fork() in a multithreaded program, the child can
          safely call only async-signal-safe functions (see
          signal-safety(7)) until such time as it calls execve(2).
    

    All of the threads except the one that called fork will vanish from the child process. If any of them had a mutex locked, then that mutex will stay locked, with no way to unlock it. If any of them had work-in-progress, that work will be unfinished, with no way (in general) for you to know how much of it was done.

    You asked, in a comment:

    so you mean if I have 5 threads started from the main thread & If I call fork from one of the thread, the rest four thread will be killed?

    After the fork call, the parent process still will have five threads, but the child process will have only one.