printf заставляет setrlimit не работать

Следуя этому ТАК вопрос а также этот ответ в частности, кажется, что вызов setrlimit после printf делает его не работающим.

Вот пример кода:

#include <stdio.h>
#include <sys/resource.h>

int main()
{
struct rlimit rlp;

FILE *fp[10000];
int i;

printf("Hello\n");

rlp.rlim_cur = 10000;
rlp.rlim_max = RLIM_INFINITY;
setrlimit(RLIMIT_NOFILE, &rlp);

getrlimit(RLIMIT_NOFILE, &rlp);
printf("limit %lld %lld\n", rlp.rlim_cur, rlp.rlim_max);

for(i=0;i<10000;i++) {
fp[i] = fopen("a.out", "r");
if(fp[i]==0) { printf("failed after %d\n", i); break; }
}

}

Вот вывод консоли:

Hello
limit 10000 9223372036854775807
failed after 4861

Если я прокомментирую первый printfВот вывод консоли:

limit 10000 9223372036854775807
failed after 9967

Есть ли причина для этого?

[Изменить] Я использую MAc OS X 10.7.5 с Xcode 4.6.2.

0

Решение

Вот лучшая версия программы, которая демонстрирует больше аспектов проблемы.

#include <stdio.h>
#include <sys/resource.h>
#include <err.h>
#include <fcntl.h>

int
main(int argc, char **argv)
{
struct rlimit rl;
int i;

rl.rlim_cur = 10;
rl.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_NOFILE, &rl))
err(1, "setrlimit");

printf("Hello\n");

rl.rlim_cur = 100;
rl.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_NOFILE, &rl))
err(1, "setrlimit");

if (getrlimit(RLIMIT_NOFILE, &rl))
err(1, "getrlimit");
printf("limit %lld\n", rl.rlim_cur);

for(i = 0; i < 10000; i++) {
FILE *fp;
#if 1
if ((fp = fopen("foo", "r")) == NULL) {
err(1, "failed after %d", i);
}
#else
if (open("foo", O_RDONLY) == -1) {
err(1, "failed after %d", i);
}
#endif
}
return 0;
}

Если вы запустите эту программу с «#if 1», измененным на «#if 0», она будет работать как положено. Похоже, что MacOS считывает лимиты для открытых файлов один раз во время инициализации stdio в libc и больше не читает их позже. Ваш первый вызов printf инициализирует stdio в libc, и это кэширует любое значение rlimit для числа открытых файлов.

Запуск dtruss на тривиальном «привет, мир» показывает:

$ cat > hw.c
#include <stdio.h>
int main() { printf("hello, world\n"); return 0; }
$ cc -Wall -o hw hw.c && sudo dtruss ./hw 2>&1 | grep rlimit
getrlimit(0x1008, 0x7FFF58875AE8, 0x7FFF8BE92470)        = 0 0
$

Что показывает, что это на самом деле то, что происходит.

Это то, что вы должны рассмотреть с Apple, хотя, пахнет как ошибка.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]