Иногда, когда я пытаюсь создать ключ с pthread_key_create
, я получаю код ошибки EAGAIN. Можно ли точно знать, почему?
Документация гласит:
Системе не хватало ресурсов, необходимых для создания другого ключа данных, специфичного для потока, или было бы превышено установленное системой ограничение на общее количество ключей на процесс [PTHREAD_KEYS_MAX].
Как проверить, был ли предел для ключей? Может быть, какой-нибудь инструмент контроля короля проверяет, сколько ключей уже открыто в системе и сколько еще можно использовать?
Одна важная вещь в нашем коде: мы используем fork()
и выполняем несколько процессов. И каждый процесс может иметь несколько потоков.
Я обнаружил, что у нас нет независимого ограничения для ключей потоков, когда мы используем fork()
. Вот небольшой пример.
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
size_t create_keys(pthread_key_t *keys, size_t number_of_keys)
{
size_t counter = 0;
for (size_t i = 0; i < number_of_keys; i++)
{
int e = pthread_key_create(keys + i, NULL);
if (e)
{
printf("ERROR (%d): index: %ld, pthread_key_create (%d)\n", getpid(), i, e);
break;
}
counter++;
}
return counter;
}
int main(int argc, char const *argv[])
{
printf("maximim number of thread keys: %ld\n", sysconf(_SC_THREAD_KEYS_MAX));
printf("process id: %d\n", getpid());
const size_t number_of_keys = 1024;
pthread_key_t keys_1[number_of_keys];
memset(keys_1, 0, number_of_keys * sizeof(pthread_key_t));
printf("INFO (%d): number of active keys: %ld\n", getpid(), create_keys(keys_1, number_of_keys));
pid_t p = fork();
if (p == 0)
{
printf("process id: %d\n", getpid());
pthread_key_t keys_2[number_of_keys];
memset(keys_2, 0, number_of_keys * sizeof(pthread_key_t));
printf("INFO (%d): number of active keys: %ld\n", getpid(), create_keys(keys_2, number_of_keys));
}
return 0;
}
Когда я запускаю этот пример в Ubuntu 16.04, я вижу, что дочерний процесс не может создать новый ключ потока, если я использую то же количество ключей, что и ограничение (1024). Но если я использую 512 ключей для родительских и дочерних процессов, я могу запустить их без ошибок.