1

I'm trying to build an application that reads from the ftrace pipes at the debug fs.

It seems that when trying to read asynchronously from trace_pipe or trace_pipe_raw using boost::asio API, the events waiting in pipe are being processed and printed to screen by the async_read handle, but new events that arrive after the program started don't trigger the async_read handle.

Running the sample code below, i'm getting a print of all events waiting in queue but i don't get any print for new events that arrive later.

The same sample works perfectly if i'm trying to read from manually created pipe using mkfifo but doesn't work for the ftrace pipes.

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <string>
#include <iostream>

namespace asio = boost::asio;
#ifdef BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
typedef asio::posix::stream_descriptor stream_descriptor;
#endif

class PipeReader
{
    typedef std::shared_ptr<PipeReader> PipeReaderPtr;
    typedef std::weak_ptr<PipeReader> PipeReaderWeakPtr;
public:
    static PipeReaderWeakPtr Create(asio::io_service& io_service, const std::string& path);

    void HandleRead(PipeReaderPtr me, const boost::system::error_code &error);
private:
    PipeReader(asio::io_service& io_service, const std::string& path);
    stream_descriptor m_pipe;
    char buf[4096];
};

PipeReader::PipeReaderWeakPtr PipeReader::Create(asio::io_service& io_service, const std::string& path)
{
    PipeReaderPtr ptr(new PipeReader(io_service, path));

    ptr->m_pipe.async_read_some(boost::asio::buffer(ptr->buf),
                                boost::bind(&PipeReader::HandleRead,
                                            ptr.get(), 
                                            ptr,
                                            asio::placeholders::error));
    return ptr;
}

PipeReader::PipeReader(asio::io_service& io_service, const std::string& path)
                       : m_pipe(io_service)
{
    int dev = open(path.c_str(), O_RDWR);
    if (dev == -1) {
        std::cout << "failed to open path - " << path << std::endl;
    }
    else
    {
        m_pipe.assign(dev);
    }
}

void PipeReader::HandleRead(PipeReaderPtr me, const boost::system::error_code &error) 
{
    if (!error) {
        std::string str(me->buf);

        std::cout << "got message: " << str << std::endl;
        m_pipe.async_read_some(boost::asio::buffer(me->buf),
                               boost::bind(&PipeReader::HandleRead,
                                           this,
                                           me,
                                           asio::placeholders::error));
    }
    else
    {
        std::cout << "got error - " << error.message() << std::endl;
    }
}


int main()
{
    boost::asio::io_service io_service;
    boost::asio::io_service::work dummy(io_service);

    PipeReader::Create(io_service, "/sys/kernel/debug/tracing/trace_pipe");

    io_service.run();   
    return 0;
}
galk
  • 61
  • 8
  • Looks like *trace_pipe* file doesn't implement async interface (`.fasync` method). It is usual for files under `debugfs`, `sysfs` and other "virtual" filesystems to implement only mostly used interfaces for access that files. – Tsyvarev Jul 12 '16 at 18:53

1 Answers1

1

I found the problem. it was a bug in the implementation of ftrace that caused the epoll to hang. The bug was fixed at kernel 3.16.

correspondence thread, commit in git hub

galk
  • 61
  • 8