繁体   English   中英

在valgrind下运行时,setrlimit失败,不允许进行操作

[英]setrlimit fails with Operation not permitted when run under valgrind

我可能会缺少某些东西,但可能不会,但是在valgrind下运行时, setrlimit函数会始终失败

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#

在valgrind下

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;
}

第一次运行,限制设置为65590,可执行文件可以将限制更改为65536,即预期

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

65536
[root@localhost kk]#

在valgrind下进行第二轮

[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内容还远远不够。

还有其他建议吗?

在允许的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)。 我认为这是因为valgrind使用此VG_(fd_hard_limit)(不可更改)来查找valgrind保留的fds与来宾fds之间的差异。

要绕过该问题,您应该获取限制,然后仅将软限制更改为硬限制以下,因为更改硬限制将被valgrind setrlimit模拟拒绝。

看来这是Valgrind的局限性之一,即在Valgrind下运行时setrlimit对硬限制的限制。 新闻中查看版本2.1.2

  • 除了当前保留的区域外,还为文件描述符实现模拟的软限制,这实际上可以用作硬限制。 现在,setrlimit系统调用仅尽可能简单地更新模拟的限制-硬限制完全不允许移动,如果尝试更改,则仅返回EPERM。 当valgrind尝试从保留区域分配描述符时,这应停止减小软限制,从而导致断言。 (这实际上来自bug#83998)。

请注意,您不是唯一一个达到此Valgrind限制的人,请参阅此github问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM