• Show log

    Commit

  • Hash : 0933fdc5
    Author : Patrick Steinhardt
    Date : 2018-05-04T13:40:54

    global: adjust init count under lock
    
    Our global initialization functions `git_libgit2_init()` and
    `git_libgit2_shutdown()` both adjust a global init counter to determine
    whether we are the first respectively last user of libgit2. On
    Unix-systems do not do so under lock, though, which opens the
    possibility of a race between these two functions:
    
        Thread 1                            Thread 2
                                git__n_inits = 0;
        git_libgit2_init();
        git_atomic_inc(&git__n_inits);
        /* git__n_inits == 1 */
                                            git_libgit2_shutdown();
                                            if (git_atomic_dec(&git__n_inits) != 0)
                                                /* git__n_inits == 0, no early exit here */
                                            pthread_mutex_lock(&_init_mutex);
                                            shutdown_common();
                                            pthread_mutex_unlock(&_init_mutex);
        pthread_mutex_lock(&_init_mutex);
        init_once();
        pthread_mutex_unlock(&_init_mutex);
    
    So we can end up in a situation where we try to shutdown shared data
    structures before they have been initialized.
    
    Fix the race by always locking `_init_mutex` before incrementing or
    decrementing `git__n_inits`.