Мне нужно помочь со следующим; Я пытался найти ответ, и я остался с вопросом.
Инспектор XE дал следующий результат: Утечка ресурсов ядра на линии
he=BIO_gethostbyname(str);
Эта строка является частью исходного кода OpenSSL, и я не могу представить, что здесь что-то не так.
Эта функция вызывается внутри:
BIO_do_connect();
Мой код
bio = BIO_new_connect(...);
if (BIO_do_connect(bio) != 1) { ... }
...
if (BIO_free(bio) != 0) { ... }
Соединение установлено успешно, единственные ошибки, которые возникают, когда я вызываю эту функцию 1000 раз одновременно с потоками.
Может ли эта программа вызвать утечку ресурсов ядра?
BIO_gethostbyname
не является (не может быть) потокобезопасным, поскольку возвращает указатель на статический буфер. В самом деле, есть упоминание об этом в биографии openssl.
struct hostent *BIO_gethostbyname(const char *name);
/* We might want a thread-safe interface too:
* struct hostent *BIO_gethostbyname_r(const char *name,
* struct hostent *result, void *buffer, size_t buflen);
* or something similar (caller allocates a struct hostent,
* pointed to by "result", and additional buffer space for the various
* substructures; if the buffer does not suffice, NULL is returned
* and an appropriate error code is set).
*/
…тем не менее, до сих пор не было реализовано ни одной функции BIO_gethostbyname_r, и в любом случае это не помогло бы вам, если бы она была, а BIO_do_connect не использовала ее.
Но отчаяния нет! Вокруг этого вызова функции есть код блокировки, так что его (вероятно) можно заставить работать. Забавно, но код блокировки не всегда делает что-либо. Я предполагаю, что вы не компилировали OpenSSL с OPENSSL_NO_LOCKING
потому что это не по умолчанию, и я не могу представить, чтобы кто-то вставил его, если бы он хотел разрабатывать многопоточные приложения, поэтому я предполагаю, что вы забыли позвонить
CRYPTO_thread_setup();
до порождения потоков, использующих OpenSSL. Это важно по той причине, что CRYPTO_thread_setup
помимо прочего, устанавливает указатель на функцию, зависящую от платформы, которая обрабатывает фактическую блокировку. Если CRYPTO_thread_setup
не вызывается, этот указатель остается NULL
, а также CRYPTO_lock
(соответствующая функция в нижней части макроса используется вокруг BIO_gethostbyname
позвони) молча ничего не сделаю. Насколько я знаю, нет никакой документации, из которой вы могли бы знать это.
Можно утверждать, что ваш оптимизм по поводу качества кодовой базы OpenSSL неуместен.