setrlimit не работает, если операция не разрешена при запуске под управлением valgrind - программирование

setrlimit не работает, если операция не разрешена при запуске под управлением valgrind

Возможно, я что-то setrlimit а может быть, но функция setrlimit не работает последовательно при запуске под valgrind

int main()
{
        const struct rlimit file_limits = { .rlim_cur = 65536, .rlim_max = 65536 };
        if ( setrlimit( RLIMIT_NOFILE, &file_limits ) )
        {
                printf(" Failed  %d", errno );
                perror(" More " );
        }
        else
        {
                printf(" Success ");
        }
        printf("\n");
        return 0;
}

Вот пример пробега

Нормальный ход

sh-4.2# ulimit -H -n
800000
sh-4.2# ulimit -S -n
500000
sh-4.2# ./rlimit
 Success
sh-4.2#

под

sh-4.2#
sh-4.2# valgrind ./rlimit
==28974== Memcheck, a memory error detector
==28974== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==28974== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==28974== Command: ./rlimit
==28974==
 More : Operation not permitted
 Failed  1
==28974==
==28974== HEAP SUMMARY:
==28974==     in use at exit: 0 bytes in 0 blocks
==28974==   total heap usage: 1 allocs, 1 frees, 568 bytes allocated
==28974==
==28974== All heap blocks were freed -- no leaks are possible
==28974==
==28974== For counts of detected and suppressed errors, rerun with: -v
==28974== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
sh-4.2#

Любые намеки на это были бы замечательными. ПРИМЕЧАНИЕ: это версия CentOS 7.4 (Final).

Редактирование №1

С минимальным рабочим кодом:

int main()
{
        const struct rlimit file_limits = { .rlim_cur = 65536, .rlim_max = 65536 };
        setrlimit( RLIMIT_NOFILE, &file_limits ) ;
        perror(" wrong ?? " );
        printf("\n");
        return 0;
}

соответствующие выходы:

[[email protected] kk]# valgrind ./rlimit
==29179== Memcheck, a memory error detector
==29179== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==29179== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==29179== Command: ./rlimit
==29179==
 wrong ?? : Operation not permitted

==29179==
==29179== HEAP SUMMARY:
==29179==     in use at exit: 0 bytes in 0 blocks
==29179==   total heap usage: 1 allocs, 1 frees, 568 bytes allocated
==29179==
==29179== All heap blocks were freed -- no leaks are possible
==29179==
==29179== For counts of detected and suppressed errors, rerun with: -v
==29179== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
[[email protected] kk]# ./rlimit
 wrong ?? : Success

это неправильно? : Операция не разрешена, сводит меня с ума :(

Редактировать # 2

Поэтому, основываясь на каком-то предложении, я попытался восстановить существующие ограничения и посмотреть, есть ли что-то в этом роде, получается поведение, выходящее за рамки моего понимания

int main()
{
        const struct rlimit file_limits = { .rlim_cur = 65536, .rlim_max = 65536 };
        struct rlimit limit;
        getrlimit(RLIMIT_NOFILE,&limit);
        printf("%d \n",limit.rlim_max);

        setrlimit( RLIMIT_NOFILE, &file_limits ) ;
        perror(" wrong ?? " );
        printf("\n");

        getrlimit(RLIMIT_NOFILE,&limit);
        printf("%d \n",limit.rlim_max);
        return 0;
}

1-й прогон, предел установлен на 65590, и исполняемый файл может изменить пределы до 65536, а именно: ожидается

[[email protected] kk]# ulimit -n
65590
[[email protected] kk]# ./rlimit
65590
 wrong ?? : Success

65536
[[email protected] kk]#

2-й прогон под контролем

[[email protected] kk]# ulimit -n
65590
[[email protected] kk]# valgrind ./rlimit
==17595== Memcheck, a memory error detector
==17595== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==17595== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==17595== Command: ./rlimit
==17595==
65578
 wrong ?? : Operation not permitted

65578
==17595==
==17595== HEAP SUMMARY:
==17595==     in use at exit: 0 bytes in 0 blocks
==17595==   total heap usage: 1 allocs, 1 frees, 568 bytes allocated
==17595==
==17595== All heap blocks were freed -- no leaks are possible
==17595==
==17595== For counts of detected and suppressed errors, rerun with: -v
==17595== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
[[email protected] kk]#

Я, вероятно, склонен сказать, что может быть valgrind резервирует несколько дескрипторов файлов для его использования на основе обсуждения здесь, пусть скажет в этом случае это 12?? Таким образом, установив предел на 65578?? Что еще более того, что программа пытается зарезервировать 65536.

Любые предложения?

4b9b3361

Ответ 1

Из разрешенного диапазона fd 0.. hard_limit valgrind резервирует набор fd для собственных целей в конце диапазона, то есть диапазон hard_limit - 11.. hard_limit, а затем имитирует новый жесткий предел, который является hard_limit - 12.

Затем он запрещает гостевому приложению изменять этот (имитируемый) жесткий предел. Вот фрагмент кода, который обрабатывает симуляцию setrlimit:

 if (((struct vki_rlimit *)(Addr)ARG2)->rlim_cur > VG_(fd_hard_limit) ||
      ((struct vki_rlimit *)(Addr)ARG2)->rlim_max != VG_(fd_hard_limit)) {
     SET_STATUS_Failure( VKI_EPERM );
  }

Как вы можете видеть, если предоставленный rlim_max отличается от моделируемого VG_ (fd_hard_limit), valgrind делает сбой setrlimit. Когда принято, valgrind изменит имитируемый мягкий предел.

Я не слишком уверен, чтобы понять, почему приведенный выше код не принимает более низкий жесткий предел и устанавливает его в моделируемый VG_ (fd_hard_limit). Я думаю, что это потому, что этот (не изменяемый) VG_ (fd_hard_limit) используется valgrind, чтобы найти разницу между зарезервированными фреймами valgrind и гостевыми файлами.

Чтобы обойти проблему, вы должны получить предел, а затем изменить только мягкий предел ниже жесткого предела, так как изменение жесткого предела будет отклонено с помощью моделирования valgrind setrlimit.

Ответ 2

Похоже, что это одно из ограничений Valgrind, а именно ограничение setrlimit для жесткого ограничения при работе под Valgrind. См. В новостях для выпуска 2.1.2:

  • Внедрите эмулированный мягкий предел для файловых дескрипторов в дополнение к текущей зарезервированной области, которая эффективно действует как жесткий предел. Системный вызов setrlimit теперь просто обновляет эмулированные лимиты как можно лучше - жесткий лимит вообще не разрешается перемещать и просто возвращает EPERM, если вы попытаетесь его изменить. Это должно прекратить сокращение мягкого предела, вызывающего утверждения, когда valgrind пытается выделить дескрипторы из зарезервированной области. (Это на самом деле произошло из-за ошибки # 83998).

Обратите внимание, что вы не единственный, кто ударил это ограничение Valgrind, см., Например, эту проблему github.