Valgrind 错误:系统调用参数 epoll_pwait(sigmask) 指向不可寻址字节

Posted

技术标签:

【中文标题】Valgrind 错误:系统调用参数 epoll_pwait(sigmask) 指向不可寻址字节【英文标题】:Valgrind error: Syscall param epoll_pwait(sigmask) points to unaddressable byte(s) 【发布时间】:2017-10-19 15:03:25 【问题描述】:

我有以下最小的示例代码。我想做的是: 在一个单独的线程中,启动一个 boost::asio::deadline_timer,这样每 x ms 就会调用一个函数 loop,完成一些事情,计时器重新设置自身,这样一直持续到无穷大。

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>

void wait(int milliseconds) 
    boost::asio::io_service ioService;
    boost::asio::deadline_timer timer(ioService, boost::posix_time::milliseconds(milliseconds));
    timer.wait();


class Foo 
public:
  boost::asio::io_service ioService;
  boost::thread* thread = nullptr;
  boost::posix_time::milliseconds duration;
  boost::asio::deadline_timer timer;
  bool shouldStop = false;

  Foo() : ioService(), duration(10), timer(ioService, duration) 
  

  ~Foo() 
    if (thread != nullptr) 
        shouldStop = true;
        wait(15);
        ioService.stop();
        thread->join();
        delete thread;
        thread = nullptr;
      
  

  void start() 
    timer.async_wait(boost::bind(&Foo::loop, this));
    thread = new boost::thread([&]()ioService.run(););
  

  void loop() 
    if (shouldStop)
      return;
    timer.expires_at(timer.expires_at() + duration);
    timer.async_wait(boost::bind(&Foo::loop, this));
  
;

int main() 
  Foo foo;
  foo.start();
  wait(1000);
  return 0;

你可以用

编译
g++ -std=c++11 -Wall -pedantic -pthread -g -I. -L/usr/local/lib -L/usr/lib -lboost_system -lpthread -lboost_thread threaded-io-service.cpp -o threaded-io-service

它工作正常,我很确定不久前valgrind 没有没有抱怨它。我最近更新了,valgrind-3.13.0 现在抱怨:

==22212== Memcheck, a memory error detector
==22212== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==22212== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==22212== Command: ./threaded-io-service
==22212== 
==22212== Thread 2:
==22212== Syscall param epoll_pwait(sigmask) points to unaddressable byte(s)
==22212==    at 0x5E62326: epoll_pwait (in /usr/lib/libc-2.26.so)
==22212==    by 0x111D50: boost::asio::detail::epoll_reactor::run(bool, boost::asio::detail::op_queue<boost::asio::detail::task_io_service_operation>&) (epoll_reactor.ipp:438)
==22212==    by 0x112EE8: boost::asio::detail::task_io_service::do_run_one(boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex>&, boost::asio::detail::task_io_service_thread_info&, boost::system::error_code const&) (task_io_service.ipp:356)
==22212==    by 0x1129F0: boost::asio::detail::task_io_service::run(boost::system::error_code&) (task_io_service.ipp:149)
==22212==    by 0x11322B: boost::asio::io_service::run() (io_service.ipp:59)
==22212==    by 0x114C9C: Foo::start()::lambda()#1::operator()() const (threaded-io-service.cpp:35)
==22212==    by 0x11E8FF: boost::detail::thread_data<Foo::start()::lambda()#1>::run() (thread.hpp:116)
==22212==    by 0x526E44E: ??? (in /usr/lib/libboost_thread.so.1.65.1)
==22212==    by 0x5045089: start_thread (in /usr/lib/libpthread-2.26.so)
==22212==    by 0x5E621BE: clone (in /usr/lib/libc-2.26.so)
==22212==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==22212== 
==22212== 
==22212== HEAP SUMMARY:
==22212==     in use at exit: 0 bytes in 0 blocks
==22212==   total heap usage: 31 allocs, 31 frees, 81,701 bytes allocated
==22212== 
==22212== All heap blocks were freed -- no leaks are possible
==22212== 
==22212== For counts of detected and suppressed errors, rerun with: -v
==22212== ERROR SUMMARY: 112 errors from 1 contexts (suppressed: 0 from 0)

这真的是一个错误吗?我发现了this bug report,人们认为这可能是 valgrind 中的一个错误。

【问题讨论】:

什么版本的 gcc 和 boost? 啊,链接的错误表明它可能取决于特定的 glibc 版本,在这种情况下,命名发行版/自定义 repos 可能更有效 【参考方案1】:

是的,这确实是那个错误,它已在上游修复(valgrind svn r16451, 2017-06-17),通过您发布的链接找到:

https://bugs.kde.org/show_bug.cgi?id=381289

Mark Wielaard 2017-06-16 15:44:30 UTC 最初报道反对 Fedora:https://bugzilla.redhat.com/show_bug.cgi?id=1462258

根据 epoll_pwait(2) 手册页:

   The  sigmask  argument  may  be  specified  as  NULL,  in  which  case
   epoll_pwait() is equivalent to epoll_wait().

但是在 valgrind 下这样做会得到:

==13887== Syscall param epoll_pwait(sigmask) points to unaddressable byte(s)
==13887==    at 0x4F2B940: epoll_pwait (epoll_pwait.c:43)
==13887==    by 0x400ADE: main (syscalls-2007.c:89)
==13887==  Address 0x0 is not stack'd, malloc'd or (recently) free'd

这是因为 sys_epoll_pwait 包装器有:

   if (ARG4)
      PRE_MEM_READ( "epoll_pwait(sigmask)", ARG5, sizeof(vki_sigset_t) );

这看起来像是一个错字(ARGS4 是超时,ARG5 是 sigmask)。

【讨论】:

以上是关于Valgrind 错误:系统调用参数 epoll_pwait(sigmask) 指向不可寻址字节的主要内容,如果未能解决你的问题,请参考以下文章

epoll使用

“epoll errno (EINTR)4” —— epoll遭遇EINTR(Interrupted system call)

C++ - 使用带有结构的 GTest 值参数化测试会导致 valgrind 错误

Valgrind错误在操作系统中有所不同

Valgrind 消息:系统调用 close() 中的文件描述符 1024 无效

epoll_ctl函数的使用