inline const char *add_to_process_id_name(const char *name)
{
   static std::string str;
   get_process_id_name(str);
   str += name;
   return str.c_str();
}
int robust_mutex_test(int argc, char *argv[])
{
    try {
        if(argc == 1) { //Parent process
            //First usual mutex tests
            {
                //  test_all_lock<RobustMutex>();
//         test_all_mutex<true, RobustMutex>();
            }
            std::cout << "robust mutex recovery test" << std::endl;

            //Remove shared memory on construction and destruction
            class shm_remove
            {
            public:
                shm_remove() {
                    shared_memory_object::remove
                    (::boost::interprocess::test::get_process_id_name());
                }
                ~shm_remove() {
                    shared_memory_object::remove
                    (::boost::interprocess::test::get_process_id_name());
                }
            } remover;

            //Construct managed shared memory
            managed_shared_memory segment(create_only, get_process_id_name(), 65536);

            //Create two robust mutexes
            RobustMutex *instance = segment.construct<RobustMutex>
                                    ("robust mutex")[2]();

            //Create a flag to notify that both mutexes are
            //locked and the owner is going to die soon.
            bool *go_ahead = segment.construct<bool> ("go ahead")(false);

            //Launch child process
            std::string s(argv[0]);
            s += " child ";
            s += get_process_id_name();
            std::cout << "... launching child" << std::endl;
            if(0 != std::system(s.c_str()))
                return 1;

            //Wait until child locks the mutexes and dies
            while(!*go_ahead) {
                detail::thread_yield();
            }

            std::cout << "... recovering mutex[0]" << std::endl;
            //First try to recover lock[0], put into consistent
            //state and relock it again
            {
                //Done, now try to lock it to see if robust
                //mutex recovery works
                instance[0].lock();
                if(!instance[0].previous_owner_dead())
                    return 1;
                instance[0].consistent();
                instance[0].unlock();
                //Since it's consistent, locking is possible again
                instance[0].lock();
                instance[0].unlock();
            }
            //Now with lock[1], but dont' put it in consistent state
            //so the mutex is no longer usable
            std::cout << "... recovering mutex[1]" << std::endl;
            {
                //Done, now try to lock it to see if robust
                //mutex recovery works
                instance[1].lock();
                if(!instance[1].previous_owner_dead())
                    return 1;
                //Unlock a recovered mutex without putting it into
                //into consistent state marks mutex as unusable.
                instance[1].unlock();
                //Since it's NOT consistent, locking is NOT possible again
                bool exception_thrown = false;
                try {
                    instance[1].lock();
                }
                catch(interprocess_exception &) {
                    exception_thrown = true;
                }
                if(!exception_thrown) {
                    return 1;
                }
            }
            //Now with lock[2], this was locked by child but not
            //unlocked
            std::cout << "... recovering mutex[2]" << std::endl;
            {
                //Done, now try to lock it to see if robust
                //mutex recovery works
                instance[2].lock();
                if(!instance[2].previous_owner_dead())
                    return 1;
                //Unlock a recovered mutex without putting it into
                //into consistent state marks mutex as unusable.
                instance[2].unlock();
                //Since it's NOT consistent, locking is NOT possible again
                bool exception_thrown = false;
                try {
                    instance[2].lock();
                }
                catch(interprocess_exception &) {
                    exception_thrown = true;
                }
                if(!exception_thrown) {
                    return 1;
                }
            }
        }
        else {
            //Open managed shared memory
            managed_shared_memory segment(open_only, argv[2]);
            //Find mutexes
            RobustMutex *instance = segment.find<RobustMutex>("robust mutex").first;
            assert(instance);
            if(std::string(argv[1]) == std::string("child")) {
                std::cout << "launched child" << std::endl;
                //Find flag
                bool *go_ahead = segment.find<bool>("go ahead").first;
                assert(go_ahead);
                //Lock, flag and die
                bool try_lock_res = instance[0].try_lock() && instance[1].try_lock();
                assert(try_lock_res);
                if(!try_lock_res)
                    return 1;

                bool *go_ahead2 = segment.construct<bool>("go ahead2")(false);
                assert(go_ahead2);
                //Launch grandchild
                std::string s(argv[0]);
                s += " grandchild ";
                s += argv[2];
                std::cout << "... launching grandchild" << std::endl;
                if(0 != std::system(s.c_str())) {
                    std::cout << "launched terminated with error" << std::endl;
                    return 1;
                }

                //Wait until child locks the 2nd mutex and dies
                while(!*go_ahead2) {
                    detail::thread_yield();
                }

                //Done, now try to lock number 3 to see if robust
                //mutex recovery works
                instance[2].lock();
                if(!instance[2].previous_owner_dead()) {
                    return 1;
                }
                *go_ahead = true;
            }
            else {
                std::cout << "launched grandchild" << std::endl;
                //grandchild locks the lock and dies
                bool *go_ahead2 = segment.find<bool>("go ahead2").first;
                assert(go_ahead2);
                //Lock, flag and die
                bool try_lock_res = instance[2].try_lock();
                assert(try_lock_res);
                if(!try_lock_res) {
                    return 1;
                }
                *go_ahead2 = true;
            }
        }
    } catch(...) {
        std::cout << "Exception thrown error!" << std::endl;
        throw;
    }
    return 0;
}
inline const char *get_process_id_name()
{
   static std::string str;
   get_process_id_name(str);
   return str.c_str();
}