setrlimit завершается неудачно, операция не разрешена при запуске под valgrind - PullRequest
0 голосов
/ 29 августа 2018

Возможно, я что-то упустил или нет, но функция 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 (финальная версия).

Правка # 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;
}

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

[root@localhost 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)
[root@localhost 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, то есть ожидается

[root@localhost kk]# ulimit -n
65590
[root@localhost kk]# ./rlimit
65590
 wrong ?? : Success

65536
[root@localhost kk]#

2й пробег, под Вальгриндом

[root@localhost kk]# ulimit -n
65590
[root@localhost 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)
[root@localhost kk]#

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

Есть еще какие-нибудь предложения для подражания?

Ответы [ 2 ]

0 голосов
/ 30 сентября 2018

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

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

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

0 голосов
/ 30 августа 2018

Из допустимого диапазона 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, чтобы найти разницу между зарезервированными FDS Valgrind и гость фдс.

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

...