Skip to content

inner_evp_generic_fetch races when called from multiple threads #13682

@ThadHouse

Description

@ThadHouse

When attempting to load EVP objects across multiple threads, the first load of some of the threads returns a null method. This occurs even when its known the method type can be loaded, and other threads succeed.

We started noticing this when we updated to 3.0.0-alpha8 from 3.0.0-alpha4. This does not reproduce on alpha 4, but does reproduce updating to alpha 9.

I've only tested that this reproduces on Windows, but its possible it reproduces on Linux as well.

The following reproduction fires up 8 threads. On anywhere from 1-5 of the threads, the first fetch of the thread will fail. Subsequent ones will pass. If you uncomment the SINGLE_THREADED define, it will only run a single thread, and that will always pass too.

#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable:4100) // Unreferenced parameter errcode in inline function
#endif
#include "openssl/err.h"
#include "openssl/ssl.h"
#ifdef _WIN32
#pragma warning(pop)
#endif

#include <thread>
#include <array>

//#define SINGLE_THREADED

int main() {
    OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
    ERR_clear_error();

    auto cb = []() {
        while (true) {
            EVP_KEYEXCH* kx = EVP_KEYEXCH_fetch(NULL, "ECDH", NULL);
            if (kx != NULL) {
                EVP_KEYEXCH_free(kx);
            }
            else {
                char buf[256];
                const char* file;
                int line;
                ERR_error_string_n(ERR_get_error_line(&file, &line), buf, sizeof(buf));
                printf("ERR: %s, file :%s:%d\n", buf, file, line);
            }
        }
    };

#ifdef SINGLE_THREADED
    std::thread thread{ cb };
    thread.join();
#else

    std::array<std::thread, 8> threads;
    for (int i = 0; i < threads.size(); ++i) {
        threads[i] = std::thread{ cb };
    }

    threads[0].join();
#endif
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions