pistacheio / pistache

A high-performance REST toolkit written in C++
https://pistacheio.github.io/pistache/
Apache License 2.0
3.18k stars 698 forks source link

Memory leaks (general) #399

Open dennisjenkins75 opened 5 years ago

dennisjenkins75 commented 5 years ago

Pistache (as of master/head, right now), has some memory leaks in it. It leaks on every bind() (minor problem) and on every processed request (major problem). These are several open bugs reporting memory leaks in various parts of pistache, however, most of those bugs were filed before the recent major rounds of code changes. In time, I plan to close those as duplicates against this issue, and track memory leaks here.

Once we fix all of the memory leaks, I intend to add memory leak checking (via valgrind) to the travis-ci, and auto-reject all PRs that introduce memory leaks.

IMHO, fixing crashes and memory leaks should be our first priority, followed by test flakiness as second priority.

One can observe the leaks by simply running valgrind against the compiled test binaries:

#!/bin/bash

DIR="."

# Ensure that we are at a pistache git root
[[ -d "${DIR}/examples" ]] || exit $?
[[ -f "${DIR}/src/common/transport.cc" ]] || exit $?

cd "./${DIR}" || exit $?

function do_check {
  CC=$1
  BUILD_DIR="${DIR}/build-${CC}"

  for TEST in ${BUILD_DIR}/tests/run_*; do
    LOG="${TEST}.xml"

    valgrind -q --xml-file=${LOG} --xml=yes --error-exitcode=1 ${TEST}
  done
}

# do_check clang
do_check gcc
$ grep "Leak_DefinitelyLost" -l build-gcc/tests/*.xml
build-gcc/tests/run_async_test.xml
build-gcc/tests/run_cookie_test_3.xml
build-gcc/tests/run_http_client_test.xml
build-gcc/tests/run_http_server_test.xml
build-gcc/tests/run_listener_test.xml
build-gcc/tests/run_payload_test.xml
build-gcc/tests/run_rest_server_test.xml
build-gcc/tests/run_streaming_test.xml
dennisjenkins75 commented 5 years ago

pistache leaks memory on every connection. The flow of the code is complex, but basically, this is what is happening (traced in gdb + valgrind of "./tests/run_rest_server_test"):

  1. Listener::run() calls Listener::handleNewConnection().
  2. Listener::handleNewConnection():
    1. Creates a shared_ptr. This is the object that leaks.
    2. Calls Listener::dispatchPeer(), which calls Transport::handleNewPeer()
  3. Transport::handleNewPeer() constructs a 'PeerEntry', which clones a 'peer' from a smart-pointer. The "use_count" is now 2. Clone is pushed into "Transport::peersQueue()".
  4. Later, pistache calls Transport::handlePeerQueue(), which calls Transport::handlePeer().
  5. (I get lost after this point)
  6. Cleanup should happen in Transport::handlePeerDisconnection()", but that it never called.
  7. At the end of the test, Endpoint::~Endpoint is called:
    1. Transport::~Transport() is called when the Endpoint is destroyed.
    2. This destroys the "peerQueue", but the "peer" smart_pointers stored in peerQueue still have use_count = 2, so they do not call ~Peer.

Somewhere a smart-pointer is being leaked, and I'm not sure where.

I am debating seeing if an older copy if pistache has a memory leak, and if not, running a "git bisect" to find when the leak began. However, I suspect that this leak has always been there.

xurxoham commented 5 years ago

I've just ran run_rest_server_test with gdb and realized that handlePeerDisconnection is called sometimes, but not every time I run the test. I think it is worth looking at Transport::handleIncoming. There are several smells in there that make me think it is not working as originally intended:

gditu commented 5 years ago

Can I ask if the leaked Peer also contains the request/response data? Or is the size of the leak fixed for each request?

I am using Pistache to serve relatively large amounts of data and I can see memory usage grow from several MB to several GB over a few days.

dennisjenkins75 commented 5 years ago

I think so. "include/pistache/peer.h" contains a few member variables, but the "data_" is of particular interest. It is the buffered data from the TCP socket.

bocse commented 5 years ago

We too have noticed this issue. Could you suggest any temporary workaround?

dennisjenkins75 commented 5 years ago

bocse: Unfortunately, no. If I had a quick work around, I would have fixed the bug outright. That last I spoke with knoweldge4igor@ and hydratim@, they were working (independently?) on rewriting the problematic code. I could be mistaken though.

I've spent a few hours digging into the leak myself. I suspect that there is a circular smart pointer reference. A destructor is never executing.

For my own project which uses Pistache, the leak is not severe enough to cause a problem until I've had 100k's of requests. Based on that, I suspect that the only thing leaking is the Peer object itself, but not the request or response buffers. But its been a few weeks since I dug into the problem.

hydratim commented 5 years ago

I'm afraid I don't have a whole lot of time atm so my proposed solution might be a little longer before it's ready. Sorry for any delays that result.

AdrianCX commented 5 years ago

Here's a possible root cause for the leak:

peer.h:

    std::unordered_map<std::string, std::shared_ptr<void>> data_;

Notice the "void". When that is hash table is destroyed, the shared_ptrs will not destroy objects.

putData does:

void
Handler::onConnection(const std::shared_ptr<Tcp::Peer>& peer) {
    peer->putData(ParserData, std::make_shared<Private::Parser<Http::Request>>());
}

If peer dies with data in the hashTable then that data is leaked. I don't see any destructor in peer that would clean the hash table.

To test: Apply fix: https://github.com/arthurafarias/pistache/commit/90b7e324a141ffb48617421a3e57e9e106a5186a

Disable SIGINT signal handler (we want to close valgrind with CTRL-C)

# valgrind --leak-check=full run_http_server

Do some requests (telnet to 9080 and close it without sending an HTTP request) Close application.

==13834== 3,168 (672 direct, 2,496 indirect) bytes in 4 blocks are definitely lost in loss record 51 of 52
==13834==    at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13834==    by 0x2D0934: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (new_allocator.h:111)
==13834==    by 0x2CFC18: std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> >&, unsigned long) (alloc_traits.h:436)
==13834==    by 0x2CF009: std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> >&) (allocated_ptr.h:104)
==13834==    by 0x2CE6E2: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, Pistache::Address>(std::_Sp_make_shared_tag, Pistache::Tcp::Peer*, std::allocator<Pistache::Tcp::Peer> const&, Pistache::Address&&) (shared_ptr_base.h:635)
==13834==    by 0x2CDBD9: std::__shared_ptr<Pistache::Tcp::Peer, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<Pistache::Tcp::Peer>, Pistache::Address>(std::_Sp_make_shared_tag, std::allocator<Pistache::Tcp::Peer> const&, Pistache::Address&&) (shared_ptr_base.h:1295)
==13834==    by 0x2CCAE0: std::shared_ptr<Pistache::Tcp::Peer>::shared_ptr<std::allocator<Pistache::Tcp::Peer>, Pistache::Address>(std::_Sp_make_shared_tag, std::allocator<Pistache::Tcp::Peer> const&, Pistache::Address&&) (shared_ptr.h:344)
==13834==    by 0x2CAC8A: std::shared_ptr<Pistache::Tcp::Peer> std::allocate_shared<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, Pistache::Address>(std::allocator<Pistache::Tcp::Peer> const&, Pistache::Address&&) (shared_ptr.h:691)
==13834==    by 0x2C8F01: std::shared_ptr<Pistache::Tcp::Peer> std::make_shared<Pistache::Tcp::Peer, Pistache::Address>(Pistache::Address&&) (shared_ptr.h:707)
==13834==    by 0x2C54A4: Pistache::Tcp::Listener::handleNewConnection() (listener.cc:392)
==13834==    by 0x2C4976: Pistache::Tcp::Listener::run() (listener.cc:270)
==13834==    by 0x2C2FD7: void Pistache::Http::Endpoint::serveImpl<void (Pistache::Tcp::Listener::*)()>(void (Pistache::Tcp::Listener::*)()) (endpoint.h:141)
==13834== 
arthurafarias commented 5 years ago

In #423 I've created a custom cmake target called test_memcheck that performs with ctest and valgrind the memory check procedure.

AdrianCX commented 5 years ago

Found another issue with code:

class Queue {
    struct Entry {
...
        ~Entry() = default;
...

This should be:

        ~Entry()
        {
            reinterpret_cast<const T*>(&storage)->~T();
        }

Because of this - peer as shared_ptr was leaking - nobody was destroying the object stored in Queue::Entry.

I'll set up a branch with fixes that seem to work with my use case

AdrianCX commented 5 years ago

Well, this is unfortunate: "remote: Permission to oktal/pistache.git denied to AdrianCX"

How can I get access? :)

In the meantime, here are the fixes: memleakfixes.diff.gz

If anyone is interested how I debugged/traced them I can add a follow up comment next few days.

hydratim commented 5 years ago

@AdrianCX fork and make a pull request; However these aren't the only memory leaks, someone'll make sure it gets reviewed, all contributions are appreciated and welcome. We are however are trying to solve some of these issues more architecturally over quick fixes, so please keep that in mind when submitting PRs.

dennisjenkins75 commented 5 years ago

Hello all. Awesome. I will test and merge these patches when I get a chance, hopefully within a few days. I want to run my own before + after valgrind runs and compare first.

@AdrianCX: As Tim (and others) recommend, please fork pistache, apply your fix to your fork, then send a PR (pull request) to merge your changes to "upstream" (the official repo). I can then easily evaluate them and merge them into the main repo.

arthurafarias commented 5 years ago

Hey guys!

The buffer struct is leaking in stream.h. This struct is self dependant so I separated it in a new file and tested. Yes, this code leads to a leak.

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <csignal>

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <memory>

struct Buffer
{
    Buffer()
        : data(nullptr), len(0), isOwned(false)
    {
    }

    Buffer(const char *const _data, size_t _len, bool _own = false)
        : data(_data), len(_len), isOwned(_own)
    {
    }

    Buffer detach(size_t fromIndex = 0) const
    {
        if (fromIndex > len)
            throw std::invalid_argument("Invalid index (> len)");

        size_t retainedLen = len - fromIndex;
        char *newData = new char[retainedLen];
        std::copy(data + fromIndex, data + len, newData);

        return Buffer(newData, retainedLen, true);
    }

    const char *const data;
    const size_t len;
    const bool isOwned;
};

int main() {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    auto b1 = Buffer("Hello", 5, true);
    // std::cout << b1.data.use_count() << std::endl;
    auto b2 = b1.detach(1);
    // std::cout << b1.data.use_count() << std::endl;
    // std::cout << b2.data.use_count() << std::endl;
    // std::cout << b1.data.get() << std::endl;
    // std::cout << b2.data.get() << std::endl;
    return 0;
}

My suggestion is to change something in architecture. See this:

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <csignal>

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <memory>

struct Buffer {

  std::shared_ptr<char[]> data;
  const size_t length;
  const bool isOwner;

  Buffer() : data(nullptr), length(0), isOwner(false) {}
  Buffer(std::shared_ptr<char[]> _data, size_t _length, bool _isOwner) : data(_data), length(_length), isOwner(_isOwner) {}
  Buffer(const char * _data, size_t _length, bool _isOwner) : length(_length), isOwner(_isOwner) {
    std::shared_ptr<char[]> sp(new char[length+1]);
    char * v = sp.get();
    strcpy(v, _data);
    data = sp;
  }

  Buffer detach(unsigned int fromIndex) {

    if (fromIndex > length) {
        std::invalid_argument("(int fromIndex) is bigger than buffer length.\n");
    }

    int newLength = length - fromIndex;
    auto currentData = data.get();

    std::shared_ptr<char[]> newDataSharedPointer(new char[newLength+1]);
    auto newData = newDataSharedPointer.get();
    memset(newData, 0, newLength+1);

    std::copy( currentData + fromIndex, currentData + length, newData );

    return Buffer(newDataSharedPointer, newLength, true);

  }

  ~Buffer() {}
};

int main() {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    auto b1 = Buffer("Hello", 5, true);
    std::cout << b1.data.use_count() << std::endl;
    auto b2 = b1.detach(1);
    std::cout << b1.data.use_count() << std::endl;
    std::cout << b2.data.use_count() << std::endl;
    std::cout << b1.data.get() << std::endl;
    std::cout << b2.data.get() << std::endl;
    return 0;
}
g++ -g -std=c++17 -Wall test.cpp -o test
valgrind -v --leak-check=yes --track-origins=yes ./test

In the same situation, this code doesn't leaks. But changes everywhere should be made. What do you think? Tomorow I gonna see if there is any other leaking code similar to this.

AdrianCX commented 5 years ago

@hydratim @dennisjenkins75 - thanks I'll fork when I have a bit of time next few days

The initial changes I made a bit in a hurry (30 min looking over code at night :) ). The 'mailbox.h' leak fix needs to be thought up a bit more with proposed changes.

i.e: There's one corner case that needs to be covered in mailbox.h - the empty 'Entry' constructor that doesn't construct anything (we cannot call destructor in storage if we don't have anything in it).

Another one is this double free if my changes go in and Queue gets destroyed:

    virtual ~Queue() {
        while (!empty()) {
            Entry* e = pop();
            e->data().~T();
            delete e;
        }
        delete tail;
    }

Queue::pop doing std::move on 'data()' is also not nice.

AdrianCX commented 5 years ago

Fixed the mailbox.h issue in a different way. Raised pull request: https://github.com/oktal/pistache/pull/425

Diff is also attached: fixes.diff.gz

Note: this does not address @arthurafarias comment/possible issue.

AdrianCX commented 5 years ago

Hi,

Thanks for merging the fix. As FYI, this is how to catch this in the future:

  1. Disable SIGINT signal handler (we want to close valgrind with CTRL-C) listener.cc - remove this code - or change the flags

    if (options_.hasFlag(Options::InstallSignalHandler)) {
        if (signal(SIGINT, handle_sigint) == SIG_ERR) {
            throw std::runtime_error("Could not install signal handler");
        }
    }
  2. Compile with debug symbols Use flag: -DCMAKE_BUILD_TYPE=Debug - or just set up '-g' in the cmake files, or both..

  3. Run valgrind with full leak check

    # valgrind --leak-check=full run_http_server
  4. Do some requests (telnet to 9080 and close it without sending an HTTP request) Close application (CTRL-C).

==13834== 3,168 (672 direct, 2,496 indirect) bytes in 4 blocks are definitely lost in loss record 51 of 52
==13834==    at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13834==    by 0x2D0934: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (new_allocator.h:111)
==13834==    by 0x2CFC18: std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> >&, unsigned long) (alloc_traits.h:436)
==13834==    by 0x2CF009: std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2> >&) (allocated_ptr.h:104)
==13834==    by 0x2CE6E2: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, Pistache::Address>(std::_Sp_make_shared_tag, Pistache::Tcp::Peer*, std::allocator<Pistache::Tcp::Peer> const&, Pistache::Address&&) (shared_ptr_base.h:635)
==13834==    by 0x2CDBD9: std::__shared_ptr<Pistache::Tcp::Peer, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<Pistache::Tcp::Peer>, Pistache::Address>(std::_Sp_make_shared_tag, std::allocator<Pistache::Tcp::Peer> const&, Pistache::Address&&) (shared_ptr_base.h:1295)
==13834==    by 0x2CCAE0: std::shared_ptr<Pistache::Tcp::Peer>::shared_ptr<std::allocator<Pistache::Tcp::Peer>, Pistache::Address>(std::_Sp_make_shared_tag, std::allocator<Pistache::Tcp::Peer> const&, Pistache::Address&&) (shared_ptr.h:344)
==13834==    by 0x2CAC8A: std::shared_ptr<Pistache::Tcp::Peer> std::allocate_shared<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, Pistache::Address>(std::allocator<Pistache::Tcp::Peer> const&, Pistache::Address&&) (shared_ptr.h:691)
==13834==    by 0x2C8F01: std::shared_ptr<Pistache::Tcp::Peer> std::make_shared<Pistache::Tcp::Peer, Pistache::Address>(Pistache::Address&&) (shared_ptr.h:707)
==13834==    by 0x2C54A4: Pistache::Tcp::Listener::handleNewConnection() (listener.cc:392)
==13834==    by 0x2C4976: Pistache::Tcp::Listener::run() (listener.cc:270)
==13834==    by 0x2C2FD7: void Pistache::Http::Endpoint::serveImpl<void (Pistache::Tcp::Listener::*)()>(void (Pistache::Tcp::Listener::*)()) (endpoint.h:141)
==13834== 
  1. We now have a shared_ptr leak... so we'd like to track refcount for the shared_ptr For that we just use GDB and set up a breakpoint where the shared_ptr is allocated
    # gdb ./run_http_server
    (gdb) b listener.cc:392
    (gdb) run

Then we trigger a new allocation - In another terminal generate a connection and close it:

# telnet 127.0.0.1 9080
CTRL-]
q
  1. You now have GDB with the breakpoint You can "CTRL-x a" to open up the nice TUI mode (and close it)

We have code:

   │396         make_non_blocking(client_fd);                                                                                                                                                                                            │
   │397                                                                                                                                                                                                                                  │
   │398         auto peer = std::make_shared<Peer>(Address::fromUnix((struct sockaddr *)&peer_addr));                                                                                                                                    │
  >│399         peer->associateFd(client_fd);                                                                                                                                                                                            │
  1. We want to set a hardware breakpoint on the refcount in the shared_ptr, so:

Disable pretty printer - we want to figure what the address of the refcount is

(gdb) disable pretty-printer

Figure out where the refcount is:

(gdb) p peer
$1 = {<std::__shared_ptr<Pistache::Tcp::Peer, (__gnu_cxx::_Lock_policy)2>> = {<std::__shared_ptr_access<Pistache::Tcp::Peer, (__gnu_cxx::_Lock_policy)2, false, false>> = {<No data fields>}, _M_ptr = 0x555555997910, _M_refcount = {
      _M_pi = 0x555555997900}}, <No data fields>}
(gdb) p peer._M_refcount
$2 = {_M_pi = 0x555555997900}
(gdb) p peer._M_refcount._M_pi
$3 = (std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2> *) 0x555555997900
(gdb) p *peer._M_refcount._M_pi
$4 = {<std::_Mutex_base<(__gnu_cxx::_Lock_policy)2>> = {<No data fields>}, 
  _vptr._Sp_counted_base = 0x555555980010 <vtable for std::_Sp_counted_ptr_inplace<Pistache::Tcp::Peer, std::allocator<Pistache::Tcp::Peer>, (__gnu_cxx::_Lock_policy)2>+16>, _M_use_count = 1, _M_weak_count = 1}
(gdb) p peer._M_refcount._M_pi._M_use_count
$5 = 1

Bingo: peer._M_refcount._M_pi._M_use_count

  1. Set hardware breakpoint

    (gdb) p &peer._M_refcount._M_pi._M_use_count
    $6 = (_Atomic_word *) 0x555555997908
    (gdb) watch *0x555555997908
    Hardware watchpoint 2: *0x555555997908
  2. Continue and hit breakpoints

(gdb) c
Continuing.

Thread 1 "run_http_server" hit Hardware watchpoint 2: *0x555555997908

Old value = 1
New value = 2
0x000055555569d456 in __gnu_cxx::__atomic_add (__mem=0x555555997908, __val=1) at /usr/include/c++/7/ext/atomicity.h:53
53    { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
(gdb) bt
#0  0x000055555569d456 in __gnu_cxx::__atomic_add (__mem=0x555555997908, __val=1) at /usr/include/c++/7/ext/atomicity.h:53
#1  0x000055555569d513 in __gnu_cxx::__atomic_add_dispatch (__mem=0x555555997908, __val=1) at /usr/include/c++/7/ext/atomicity.h:96
#2  0x00005555556a44e1 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_add_ref_copy (this=0x555555997900) at /usr/include/c++/7/bits/shared_ptr_base.h:138
#3  0x00005555556a1589 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count (this=0x7fffffffda28, __r=...) at /usr/include/c++/7/bits/shared_ptr_base.h:691
#4  0x00005555557021df in std::__shared_ptr<Pistache::Tcp::Peer, (__gnu_cxx::_Lock_policy)2>::__shared_ptr (this=0x7fffffffda20) at /usr/include/c++/7/bits/shared_ptr_base.h:1121
#5  0x0000555555702205 in std::shared_ptr<Pistache::Tcp::Peer>::shared_ptr (this=0x7fffffffda20) at /usr/include/c++/7/bits/shared_ptr.h:119
#6  0x00005555556ff429 in Pistache::Tcp::Transport::handleNewPeer (this=0x555555997140, peer=...) at /home/adrian/work/pistache/pistache/src/common/transport.cc:51
#7  0x0000555555711a18 in Pistache::Tcp::Listener::dispatchPeer (this=0x555555994d00, peer=...) at /home/adrian/work/pistache/pistache/src/server/listener.cc:415
#8  0x00005555557118d2 in Pistache::Tcp::Listener::handleNewConnection (this=0x555555994d00) at /home/adrian/work/pistache/pistache/src/server/listener.cc:406
#9  0x0000555555710d69 in Pistache::Tcp::Listener::run (this=0x555555994d00) at /home/adrian/work/pistache/pistache/src/server/listener.cc:276
#10 0x000055555570f33c in Pistache::Http::Endpoint::serveImpl<void (Pistache::Tcp::Listener::*)()> (this=0x555555994cf0, 
    method=(void (Pistache::Tcp::Listener::*)(Pistache::Tcp::Listener * const)) 0x555555710ba0 <Pistache::Tcp::Listener::run()>) at /home/adrian/work/pistache/pistache/include/pistache/endpoint.h:141
#11 0x000055555570efbd in Pistache::Http::Endpoint::serve (this=0x555555994cf0) at /home/adrian/work/pistache/pistache/src/server/endpoint.cc:77
#12 0x000055555569d817 in main (argc=1, argv=0x7fffffffde68) at /home/adrian/work/pistache/pistache/examples/http_server.cc:187
(gdb) c
Continuing.
[Switching to Thread 0x7ffff6e85700 (LWP 3596)]

Thread 2 "run_http_server" hit Hardware watchpoint 2: *0x555555997908

Old value = 2
New value = 1
0x000055555569d43d in __gnu_cxx::__exchange_and_add (__mem=0x555555997908, __val=-1) at /usr/include/c++/7/ext/atomicity.h:49
49    { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
(gdb) bt
#0  0x000055555569d43d in __gnu_cxx::__exchange_and_add (__mem=0x555555997908, __val=-1) at /usr/include/c++/7/ext/atomicity.h:49
#1  0x000055555569d4d0 in __gnu_cxx::__exchange_and_add_dispatch (__mem=0x555555997908, __val=-1) at /usr/include/c++/7/ext/atomicity.h:82
#2  0x00005555556a43a5 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x555555997900) at /usr/include/c++/7/bits/shared_ptr_base.h:151
#3  0x00005555556a14a9 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x7ffff0000b78, __in_chrg=<optimized out>) at /usr/include/c++/7/bits/shared_ptr_base.h:684
#4  0x00005555556c17de in std::__shared_ptr<Pistache::Tcp::Peer, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=0x7ffff0000b70, __in_chrg=<optimized out>) at /usr/include/c++/7/bits/shared_ptr_base.h:1123
#5  0x00005555556c17fa in std::shared_ptr<Pistache::Tcp::Peer>::~shared_ptr (this=0x7ffff0000b70, __in_chrg=<optimized out>) at /usr/include/c++/7/bits/shared_ptr.h:93
#6  0x000055555570ca2c in std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> >::~pair (this=0x7ffff0000b68, __in_chrg=<optimized out>) at /usr/include/c++/7/bits/stl_pair.h:198
#7  0x000055555570ca4c in __gnu_cxx::new_allocator<std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> > >::destroy<std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> > > (this=0x7ffff6e8399f, __p=0x7ffff0000b68)
    at /usr/include/c++/7/ext/new_allocator.h:140
#8  0x000055555570b52a in std::allocator_traits<std::allocator<std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> > > >::destroy<std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> > > (__a=..., __p=0x7ffff0000b68)
    at /usr/include/c++/7/bits/alloc_traits.h:487
#9  0x0000555555709564 in std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> >, false> > >::_M_deallocate_node (this=0x555555997258, __n=0x7ffff0000b60)
    at /usr/include/c++/7/bits/hashtable_policy.h:2084
#10 0x000055555570a2d3 in std::_Hashtable<int, std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> >, std::allocator<std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> > >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_erase (this=0x555555997258, __bkt=0, 
    __prev_n=0x555555997268, __n=0x7ffff0000b60) at /usr/include/c++/7/bits/hashtable.h:1887
#11 0x0000555555707d14 in std::_Hashtable<int, std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> >, std::allocator<std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> > >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::erase (this=0x555555997258, __it=...)
    at /usr/include/c++/7/bits/hashtable.h:1862
#12 0x00005555557055ef in std::_Hashtable<int, std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> >, std::allocator<std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> > >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::erase (this=0x555555997258, __it=...)
    at /usr/include/c++/7/bits/hashtable.h:755
#13 0x0000555555703b09 in std::unordered_map<int, std::shared_ptr<Pistache::Tcp::Peer>, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, std::shared_ptr<Pistache::Tcp::Peer> > > >::erase (this=0x555555997258, 
    __position=...) at /usr/include/c++/7/bits/unordered_map.h:800
#14 0x00005555556ffe9a in Pistache::Tcp::Transport::handlePeerDisconnection (this=0x555555997140, peer=...) at /home/adrian/work/pistache/pistache/src/common/transport.cc:188
#15 0x00005555556ffd21 in Pistache::Tcp::Transport::handleIncoming (this=0x555555997140, peer=...) at /home/adrian/work/pistache/pistache/src/common/transport.cc:163
#16 0x00005555556ff797 in Pistache::Tcp::Transport::onReady (this=0x555555997140, fds=...) at /home/adrian/work/pistache/pistache/src/common/transport.cc:83
#17 0x0000555555722a19 in Pistache::Aio::SyncImpl::handleFds (this=0x555555995060, events=...) at /home/adrian/work/pistache/pistache/src/common/reactor.cc:189
#18 0x0000555555722542 in Pistache::Aio::SyncImpl::runOnce (this=0x555555995060) at /home/adrian/work/pistache/pistache/src/common/reactor.cc:149
#19 0x0000555555722697 in Pistache::Aio::SyncImpl::run (this=0x555555995060) at /home/adrian/work/pistache/pistache/src/common/reactor.cc:162
#20 0x0000555555723b58 in Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}::operator()() const (__closure=0x555555997648) at /home/adrian/work/pistache/pistache/src/common/reactor.cc:470
#21 0x000055555572602b in std::__invoke_impl<void, Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>(std::__invoke_other, Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}&&) (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#22 0x0000555555724bc8 in std::__invoke<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>(std::__invoke_result&&, (Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}&&)...) (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#23 0x000055555572ac84 in std::thread::_Invoker<std::tuple<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (this=0x555555997648) at /usr/include/c++/7/thread:234
#24 0x000055555572ac27 in std::thread::_Invoker<std::tuple<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}> >::operator()() (this=0x555555997648) at /usr/include/c++/7/thread:243
#25 0x000055555572abc6 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}> > >::_M_run() (this=0x555555997640) at /usr/include/c++/7/thread:186
#26 0x00007ffff78ea57f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#27 0x00007ffff7bbd6db in start_thread (arg=0x7ffff6e85700) at pthread_create.c:463
#28 0x00007ffff734588f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
  1. As you can see - we only have 1 refcount remaining. It was increased via:
    #6  0x00005555556ff429 in Pistache::Tcp::Transport::handleNewPeer (this=0x555555997140, peer=...) at /home/adrian/work/pistache/pistache/src/common/transport.cc:51
    #7  0x0000555555711a18 in Pistache::Tcp::Listener::dispatchPeer (this=0x555555994d00, peer=...) at /home/adrian/work/pistache/pistache/src/server/listener.cc:415
    #8  0x00005555557118d2 in Pistache::Tcp::Listener::handleNewConnection (this=0x555555994d00) at /home/adrian/work/pistache/pistache/src/server/listener.cc:406
    #9  0x0000555555710d69 in Pistache::Tcp::Listener::run (this=0x555555994d00) at /home/adrian/work/pistache/pistache/src/server/listener.cc:276

where code is:

void
Transport::handleNewPeer(const std::shared_ptr<Tcp::Peer>& peer) {
    auto ctx = context();
    const bool isInRightThread = std::this_thread::get_id() == ctx.thread();
    if (!isInRightThread) {
        PeerEntry entry(peer);
        peersQueue.push(std::move(entry));

So, it leaks when pushed to peersQueue. peersQueue doesn't seem to decrease it. With a bit of looking over code we see that peersQueue is a lock free queue and the shared_ptr is stored via inplace new in a local storage and that's never cleared.

Hope it helps, Project looks fun, I'll see if I can help with other bugs.

Regards, Adrian Cruceru

dennisjenkins75 commented 5 years ago

Really cool!

I did not know about "disable pretty-printer". Thank you very much for your research and fixes on the memory leaks.

Once all memory leaks are fixed, I intend to have a memcheck run as a required test in travis-ci. Any failures for bad pointer use or leaked memory will cause test failure. Also, once the leaks are fixed, we can proceed with declaring a "0.1" release. I know a Gentoo maintainer who will help get Pistache into Gentoo, and Kip (or someone else here) is working on Debian and/or Ubuntu packaging.

knowledge4igor commented 5 years ago

Good goal to fix all memory leaks, I'm also working in this direction.

AdrianCX commented 5 years ago

@dennisjenkins75 - nice work with test_memcheck. Can you add '--track-origins=yes' to valgrind parameters?

I fixed remaining issues in the test target and raised pull request: https://github.com/oktal/pistache/pull/430

note regarding: "I intend to have a memcheck run as a required test in travis-ci."

Consider allowing commits that just increase test targets - there may be remaining issues that unit tests do not properly cover.

kiplingw commented 5 years ago

Bravo everyone. Love test_memcheck target.

gditu commented 5 years ago

All this looks amazing! Thank you to all involved. I plan to update and test the latest code, since I had quite large memory leaks.

Are there additional known leaks that have not been resolved?

AdrianCX commented 5 years ago

I did not see any remaining in unit tests or my testing.

If you spot one with valgrind you can post it here and I/someone else can help fix it.

arthurafarias commented 5 years ago

@AdrianCX I am using Valgrind in all test cases. And the test shows that some defects remain.

-- Processing memory checking output:
12/22 MemCheck: #12: http_server_test .................   Defects: 3
13/22 MemCheck: #13: http_client_test .................   Defects: 1
16/22 MemCheck: #16: payload_test .....................   Defects: 2
MemCheck log files can be found here: ( * corresponds to test number)
/home/arthur/Desktop/libpistache-github/build/Testing/Temporary/MemoryChecker.*.log
Memory checking results:
Memory Leak - 6
Built target test_memcheck

MemoryChecker.12.log MemoryChecker.13.log MemoryChecker.16.log

AdrianCX commented 5 years ago

Thanks, I'll try and take a look next few days.

At first glance it seems like another shared_ptr leak but it seems small (one leak per init() call)

Same technique with watchpoints on shared_ptr refcount should work here as well https://github.com/oktal/pistache/issues/399#issuecomment-459957250

arthurafarias commented 5 years ago

Great, I will try to follow your steps and see if I can fix this by myself.

AdrianCX commented 5 years ago

Cool, try and fix the "Definitely" items, the indirect ones will go away after that. If anything feel free to leave an email and we can chat.

I will also try and take a look in 1-2 days.

arthurafarias commented 5 years ago

Okay

kiplingw commented 5 years ago

@AdrianCX I am using Valgrind in all test cases. And the test shows that some defects remain.


-- Processing memory checking output:
12/22 MemCheck: #12: http_server_test .................   Defects: 3
13/22 MemCheck: #13: http_client_test .................   Defects: 1
16/22 MemCheck: #16: payload_test .....................   Defects: 2

When I ran the same target I actually noticed my results were the same as yours except payload_test noted 158 defects.

AdrianCX commented 5 years ago

That looks like a reporting issue (158 defects)

There are only 2 definite memory leaks on payload_test

$ grep -nir definite ./MemoryChecker.16.log 
1684:==613== 10,437 (480 direct, 9,957 indirect) bytes in 1 blocks are definitely lost in loss record 61 of 62
1711:==613== 10,789 (224 direct, 10,565 indirect) bytes in 1 blocks are definitely lost in loss record 62 of 62

There are ~62 indirect ones. @kiplingw I'm not sure where you got 158, can you attach your log file + git revision you tested on?

kiplingw commented 5 years ago

@AdrianCX, I am so sorry, but I am not able to reproduce the 158 defects reported for test 16/22. Since I re-ran the target I am replicating your findings. If it happens again I will be sure to preserve the log for you.

AdrianCX commented 5 years ago

Took a look, this really looks like a test issue - stack corruption that's not caught by valgrind, see analysis below. Since there are some issues with the test, please improve on it and if there are still leaks I can take a better look.

Notes:

This is the actual code:

void testPayloads(Http::Client & client, std::string url, PayloadTestSets & testPayloads) {
   // Client tests to make sure the payload is enforced
    std::mutex resultsetMutex;
    PayloadTestSets test_results;
    std::vector<Async::Promise<Http::Response> > responses;
    for (auto & t : testPayloads) {
        std::string payload(t.bytes, 'A');
        auto response = client.post(url).body(payload).send();
        response.then([t,&test_results,&resultsetMutex](Http::Response rsp) {
                TestSet res(t);
                res.actualCode = rsp.code();
                {
                    std::unique_lock<std::mutex> lock(resultsetMutex);
                    test_results.push_back(res);
                }
                }, Async::IgnoreException);
        responses.push_back(std::move(response));
    }

    auto sync = Async::whenAll(responses.begin(), responses.end());
    Async::Barrier<std::vector<Http::Response>> barrier(sync);
    barrier.wait_for(std::chrono::milliseconds(500));

    for (auto & result : test_results) {
        ASSERT_EQ(result.expectedCode, result.actualCode);
    }
}

Issues:

  1. Please do NOT give references to stack variables to a lambda...

    std::mutex resultsetMutex;
    PayloadTestSets test_results;

    Valgrind can't catch issues with stack variables If threads behind the scene finish after the test completes it will corrupt memory.

  2. Code does not wait for promises / connections. If connections are slower then 500ms they will finish later and crash or just leak or something.

    barrier.wait_for(std::chrono::milliseconds(500));

example crash:

==10510== Process terminating with default action of signal 11 (SIGSEGV)
==10510==  Bad permissions for mapped region at address 0x70E6C5
==10510==    at 0x513C55: void __gnu_cxx::new_allocator<TestSet>::construct<TestSet, TestSet const&>(TestSet*, TestSet const&) (new_allocator.h:136)
==10510==    by 0x50D288: void std::allocator_traits<std::allocator<TestSet> >::construct<TestSet, TestSet const&>(std::allocator<TestSet>&, TestSet*, TestSet const&) (alloc_traits.h:475)
==10510==    by 0x504B47: std::vector<TestSet, std::allocator<TestSet> >::push_back(TestSet const&) (stl_vector.h:943)
==10510==    by 0x4F2F4B: testPayloads(Pistache::Http::Client&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<TestSet, std::allocator<TestSet> >&)::{lambda(Pistache::Http::Response)#1}::operator()(Pistache::Http::Response) const (payload_test.cc:44)
==10510==    by 0x4FA56C: Pistache::Async::Private::impl::Continuation<Pistache::Http::Response, testPayloads(Pistache::Http::Client&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<TestSet, std::allocator<TestSet> >&)::{lambda(Pistache::Http::Response)#1}, Pistache::Async::Private::IgnoreException, void (Pistache::Http::Response)>::doResolve(std::shared_ptr<Pistache::Async::Private::CoreT<Pistache::Http::Response> > const&) (async.h:468)
==10510==    by 0x5300C7: Pistache::Async::Private::Continuable<Pistache::Http::Response>::resolve(std::shared_ptr<Pistache::Async::Private::Core> const&) (async.h:293)
==10510==    by 0x6ED353: bool Pistache::Async::Resolver::operator()<Pistache::Http::Response>(Pistache::Http::Response&&) const (async.h:778)
==10510==    by 0x6D7DB0: Pistache::Http::Connection::handleResponsePacket(char const*, unsigned long) (client.cc:459)
==10510==    by 0x6D661B: Pistache::Http::Transport::handleResponsePacket(std::shared_ptr<Pistache::Http::Connection> const&, char const*, unsigned long) (client.cc:345)
==10510==    by 0x6D6311: Pistache::Http::Transport::handleIncoming(std::shared_ptr<Pistache::Http::Connection>) (client.cc:324)
==10510==    by 0x6D3C7E: Pistache::Http::Transport::onReady(Pistache::Aio::FdSet const&) (client.cc:152)
==10510==    by 0x713716: Pistache::Aio::SyncImpl::handleFds(std::vector<Pistache::Polling::Event, std::allocator<Pistache::Polling::Event> >) const (reactor.cc:189)
kiplingw commented 5 years ago

Hey @AdrianCX. I can't comment on that code, but I say that there's a general consensus that Http::Client is not really ready for production code. Many of us don't use it at all and instead use C++ bindings for curl or something else. My guess is there's probably some memory leaks in Http::Client as well.

AdrianCX commented 5 years ago

@kiplingw Thanks, that's good info, I will try and update the unit test / fix any issues I see while doing that.

Looking over Http::Client there is some weird logic involving multi-threading - doesn't seem very safe to me so your note is valid - not really ready for production code.

arthurafarias commented 5 years ago

Interesting, the introduction of a timeout to RequestBuilder is leading to client leak.

arthurafarias commented 5 years ago

I Ran the same test with -fsanitize=address and this is the result.

Indirect leak of 4096 byte(s) in 128 object(s) allocated from:
operator new(unsigned long)
__gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace>::allocate(unsigned long, void const*)
std::allocator_traits<std::allocator>::allocate(std::allocator<std::_Sp_counted_ptr_inplace>&, unsigned long)
std::__allocated_ptr<std::allocator> std::__allocate_guarded<std::allocator>(std::allocator<std::_Sp_counted_ptr_inplace>&)
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::TimerPool::Entry, std::allocator>(std::_Sp_make_shared_tag, Pistache::TimerPool::Entry*, std::allocator<Pistache::TimerPool::Entry> const&)
std::__shared_ptr<Pistache::TimerPool::Entry, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::TimerPool::Entry> const&)
std::shared_ptr<Pistache::TimerPool::Entry>::shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::TimerPool::Entry> const&)
std::shared_ptr<Pistache::TimerPool::Entry> std::allocate_shared<Pistache::TimerPool::Entry, std::allocator>(std::allocator<Pistache::TimerPool::Entry> const&)
std::shared_ptr<Pistache::TimerPool::Entry> std::make_shared<Pistache::TimerPool::Entry>()
Pistache::TimerPool::TimerPool(unsigned long)
Pistache::Http::Connection::Connection()
void __gnu_cxx::new_allocator<Pistache::Http::Connection>::construct<Pistache::Http::Connection>(Pistache::Http::Connection*)
void std::allocator_traits<std::allocator>::construct<Pistache::Http::Connection>(std::allocator<Pistache::Http::Connection>&, Pistache::Http::Connection*)
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::Http::Connection, std::allocator>(std::_Sp_make_shared_tag, Pistache::Http::Connection*, std::allocator<Pistache::Http::Connection> const&)
std::__shared_ptr<Pistache::Http::Connection, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection>::shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::allocate_shared<Pistache::Http::Connection, std::allocator>(std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::make_shared<Pistache::Http::Connection>()
Pistache::Http::ConnectionPool::pickConnection(std::__cxx11::basic_string<char, std::char_traits, std::allocator> const&)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 2048 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
__gnu_cxx::new_allocator<std::shared_ptr>::allocate(unsigned long, void const*)
std::allocator_traits<std::allocator>::allocate(std::allocator<std::shared_ptr>&, unsigned long)
std::_Vector_base<std::shared_ptr, std::allocator>::_M_allocate(unsigned long)
void std::vector<std::shared_ptr, std::allocator>::_M_realloc_insert<std::shared_ptr>(__gnu_cxx::__normal_iterator<std::shared_ptr*, std::vector>, std::shared_ptr<Pistache::TimerPool::Entry>&&)
std::shared_ptr<Pistache::TimerPool::Entry>& std::vector<std::shared_ptr, std::allocator>::emplace_back<std::shared_ptr>(std::shared_ptr<Pistache::TimerPool::Entry>&&)
std::vector<std::shared_ptr, std::allocator>::push_back(std::shared_ptr<Pistache::TimerPool::Entry>&&)
Pistache::TimerPool::TimerPool(unsigned long)
Pistache::Http::Connection::Connection()
void __gnu_cxx::new_allocator<Pistache::Http::Connection>::construct<Pistache::Http::Connection>(Pistache::Http::Connection*)
void std::allocator_traits<std::allocator>::construct<Pistache::Http::Connection>(std::allocator<Pistache::Http::Connection>&, Pistache::Http::Connection*)
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::Http::Connection, std::allocator>(std::_Sp_make_shared_tag, Pistache::Http::Connection*, std::allocator<Pistache::Http::Connection> const&)
std::__shared_ptr<Pistache::Http::Connection, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection>::shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::allocate_shared<Pistache::Http::Connection, std::allocator>(std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::make_shared<Pistache::Http::Connection>()
Pistache::Http::ConnectionPool::pickConnection(std::__cxx11::basic_string<char, std::char_traits, std::allocator> const&)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 480 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
__gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace>::allocate(unsigned long, void const*)
std::allocator_traits<std::allocator>::allocate(std::allocator<std::_Sp_counted_ptr_inplace>&, unsigned long)
std::__allocated_ptr<std::allocator> std::__allocate_guarded<std::allocator>(std::allocator<std::_Sp_counted_ptr_inplace>&)
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::Http::Connection, std::allocator>(std::_Sp_make_shared_tag, Pistache::Http::Connection*, std::allocator<Pistache::Http::Connection> const&)
std::__shared_ptr<Pistache::Http::Connection, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection>::shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::allocate_shared<Pistache::Http::Connection, std::allocator>(std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::make_shared<Pistache::Http::Connection>()
Pistache::Http::ConnectionPool::pickConnection(std::__cxx11::basic_string<char, std::char_traits, std::allocator> const&)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 384 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
void Pistache::Queue<Pistache::Http::Connection::RequestData>::push<Pistache::Http::Connection::RequestData>(Pistache::Http::Connection::RequestData&&)
operator()
callAsync<Pistache::Http::Response, Pistache::Http::Connection::asyncPerform(const Pistache::Http::Request&, std::chrono::milliseconds, Pistache::Http::Connection::OnDone)::>
Promise<Pistache::Http::Connection::asyncPerform(const Pistache::Http::Request&, std::chrono::milliseconds, Pistache::Http::Connection::OnDone)::>
Pistache::Http::Connection::asyncPerform(Pistache::Http::Request const&, std::chrono::duration<long, std::ratio>, std::function<void ()>)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 224 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
__gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace>::allocate(unsigned long, void const*)
std::allocator_traits<std::allocator>::allocate(std::allocator<std::_Sp_counted_ptr_inplace>&, unsigned long)
std::__allocated_ptr<std::allocator> std::__allocate_guarded<std::allocator>(std::allocator<std::_Sp_counted_ptr_inplace>&)
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::Http::Transport, std::allocator, Pistache::Http::Transport const&>(std::_Sp_make_shared_tag, Pistache::Http::Transport*, std::allocator<Pistache::Http::Transport> const&, Pistache::Http::Transport const&)
std::__shared_ptr<Pistache::Http::Transport, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator, Pistache::Http::Transport const&>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Transport> const&, Pistache::Http::Transport const&)
std::shared_ptr<Pistache::Http::Transport>::shared_ptr<std::allocator, Pistache::Http::Transport const&>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Transport> const&, Pistache::Http::Transport const&)
std::shared_ptr<Pistache::Http::Transport> std::allocate_shared<Pistache::Http::Transport, std::allocator, Pistache::Http::Transport const&>(std::allocator<Pistache::Http::Transport> const&, Pistache::Http::Transport const&)
std::shared_ptr<Pistache::Http::Transport> std::make_shared<Pistache::Http::Transport, Pistache::Http::Transport const&>(Pistache::Http::Transport const&)
Pistache::Http::Transport::clone() const
Pistache::Aio::AsyncImpl::addHandler(std::shared_ptr<Pistache::Aio::Handler> const&, bool)
Pistache::Aio::Reactor::addHandler(std::shared_ptr<Pistache::Aio::Handler> const&)
Pistache::Http::Client::init(Pistache::Http::Client::Options const&)
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 200 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
__gnu_cxx::new_allocator<std::__detail::_Hash_node>::allocate(unsigned long, void const*)
std::allocator_traits<std::allocator>::allocate(std::allocator<std::__detail::_Hash_node>&, unsigned long)
std::__detail::_Hash_node<std::pair, false>* std::__detail::_Hashtable_alloc<std::allocator>::_M_allocate_node<std::pair>(std::pair<int, Pistache::Http::Transport::ConnectionEntry>&&)
std::pair<std::__detail::_Node_iterator, bool> std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_emplace<std::pair>(std::integral_constant<bool, true>, std::pair<int, Pistache::Http::Transport::ConnectionEntry>&&)
std::pair<std::__detail::_Node_iterator, bool> std::__detail::_Insert<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits, false>::insert<std::pair, void>(std::pair<int, Pistache::Http::Transport::ConnectionEntry>&&)
std::pair<std::__detail::_Node_iterator, bool> std::unordered_map<int, Pistache::Http::Transport::ConnectionEntry, std::hash, std::equal_to, std::allocator>::insert<std::pair, void>(std::pair<int, Pistache::Http::Transport::ConnectionEntry>&&)
Pistache::Http::Transport::handleConnectionQueue()
Pistache::Http::Transport::onReady(Pistache::Aio::FdSet const&)
Pistache::Aio::SyncImpl::handleFds(std::vector<Pistache::Polling::Event, std::allocator>) const
Pistache::Aio::SyncImpl::runOnce()
Pistache::Aio::SyncImpl::run()
Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}::operator()() const
void std::__invoke_impl<void, Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>(std::__invoke_other, Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}&&)
std::__invoke_result<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>::type std::__invoke<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>(std::__invoke_result&&, (Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}&&)...)
decltype (__invoke((_S_declval<0ul>)())) std::thread::_Invoker<std::tuple>::_M_invoke<0ul>(std::_Index_tuple<0ul>)
std::thread::_Invoker<std::tuple>::operator()()
std::thread::_State_impl<std::thread::_Invoker>::_M_run()
(libstdc++.so.6+0x0000000bd57e)
Indirect leak of 192 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
void Pistache::Queue<Pistache::Http::Transport::ConnectionEntry>::push<Pistache::Http::Transport::ConnectionEntry>(Pistache::Http::Transport::ConnectionEntry&&)
void Pistache::PollableQueue<Pistache::Http::Transport::ConnectionEntry>::push<Pistache::Http::Transport::ConnectionEntry>(Pistache::Http::Transport::ConnectionEntry&&)
operator()
callAsync<void, Pistache::Http::Transport::asyncConnect(std::shared_ptr, const sockaddr*, socklen_t)::>
Promise<Pistache::Http::Transport::asyncConnect(std::shared_ptr, const sockaddr*, socklen_t)::>
Pistache::Http::Transport::asyncConnect(std::shared_ptr<Pistache::Http::Connection>, sockaddr const*, unsigned int)
Pistache::Http::Connection::connect(Pistache::Address const&)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 112 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
Pistache::Async::Promise<void>::Promise()
then<Pistache::Http::Connection::connect(const Pistache::Address&)::, Pistache::Http::ExceptionPrinter>
Pistache::Http::Connection::connect(Pistache::Address const&)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 112 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
__gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace>::allocate(unsigned long, void const*)
std::allocator_traits<std::allocator>::allocate(std::allocator<std::_Sp_counted_ptr_inplace>&, unsigned long)
std::__allocated_ptr<std::allocator> std::__allocate_guarded<std::allocator>(std::allocator<std::_Sp_counted_ptr_inplace>&)
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::Async::Private::CoreT, std::allocator>(std::_Sp_make_shared_tag, Pistache::Async::Private::CoreT<void>*, std::allocator<Pistache::Async::Private::CoreT> const&)
std::__shared_ptr<Pistache::Async::Private::CoreT, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Async::Private::CoreT> const&)
std::shared_ptr<Pistache::Async::Private::CoreT>::shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Async::Private::CoreT> const&)
std::shared_ptr<Pistache::Async::Private::CoreT> std::allocate_shared<Pistache::Async::Private::CoreT, std::allocator>(std::allocator<Pistache::Async::Private::CoreT> const&)
std::shared_ptr<Pistache::Async::Private::CoreT> std::make_shared<Pistache::Async::Private::CoreT>()
Promise<Pistache::Http::Transport::asyncConnect(std::shared_ptr, const sockaddr*, socklen_t)::>
Pistache::Http::Transport::asyncConnect(std::shared_ptr<Pistache::Http::Connection>, sockaddr const*, unsigned int)
Pistache::Http::Connection::connect(Pistache::Address const&)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 104 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
Pistache::Queue<Pistache::Http::Transport::RequestEntry>::Queue()
Pistache::PollableQueue<Pistache::Http::Transport::RequestEntry>::PollableQueue()
Pistache::Http::Transport::Transport(Pistache::Http::Transport const&)
void __gnu_cxx::new_allocator<Pistache::Http::Transport>::construct<Pistache::Http::Transport, Pistache::Http::Transport const&>(Pistache::Http::Transport*, Pistache::Http::Transport const&)
void std::allocator_traits<std::allocator>::construct<Pistache::Http::Transport, Pistache::Http::Transport const&>(std::allocator<Pistache::Http::Transport>&, Pistache::Http::Transport*, Pistache::Http::Transport const&)
std::_Sp_counted_ptr_inplace<Pistache::Http::Transport, std::allocator, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<Pistache::Http::Transport const&>(std::allocator<Pistache::Http::Transport>, Pistache::Http::Transport const&)
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::Http::Transport, std::allocator, Pistache::Http::Transport const&>(std::_Sp_make_shared_tag, Pistache::Http::Transport*, std::allocator<Pistache::Http::Transport> const&, Pistache::Http::Transport const&)
std::__shared_ptr<Pistache::Http::Transport, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator, Pistache::Http::Transport const&>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Transport> const&, Pistache::Http::Transport const&)
std::shared_ptr<Pistache::Http::Transport>::shared_ptr<std::allocator, Pistache::Http::Transport const&>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Transport> const&, Pistache::Http::Transport const&)
std::shared_ptr<Pistache::Http::Transport> std::allocate_shared<Pistache::Http::Transport, std::allocator, Pistache::Http::Transport const&>(std::allocator<Pistache::Http::Transport> const&, Pistache::Http::Transport const&)
std::shared_ptr<Pistache::Http::Transport> std::make_shared<Pistache::Http::Transport, Pistache::Http::Transport const&>(Pistache::Http::Transport const&)
Pistache::Http::Transport::clone() const
Pistache::Aio::AsyncImpl::addHandler(std::shared_ptr<Pistache::Aio::Handler> const&, bool)
Pistache::Aio::Reactor::addHandler(std::shared_ptr<Pistache::Aio::Handler> const&)
Pistache::Http::Client::init(Pistache::Http::Client::Options const&)
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 80 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
allocate
allocate
__allocate_guarded<std::allocator>
__shared_count<Pistache::Async::Private::Continuation, std::allocator, std::shared_ptr&, Pistache::Http::Connection::connect(const Pistache::Address&)::&, Pistache::Http::ExceptionPrinter&>
__shared_ptr<std::allocator, std::shared_ptr&, Pistache::Http::Connection::connect(const Pistache::Address&)::&, Pistache::Http::ExceptionPrinter&>
shared_ptr<std::allocator, std::shared_ptr&, Pistache::Http::Connection::connect(const Pistache::Address&)::&, Pistache::Http::ExceptionPrinter&>
allocate_shared<Pistache::Async::Private::Continuation, std::allocator, std::shared_ptr&, Pistache::Http::Connection::connect(const Pistache::Address&)::&, Pistache::Http::ExceptionPrinter&>
make_shared<Pistache::Async::Private::Continuation, std::shared_ptr&, Pistache::Http::Connection::connect(const Pistache::Address&)::&, Pistache::Http::ExceptionPrinter&>
then<Pistache::Http::Connection::connect(const Pistache::Address&)::, Pistache::Http::ExceptionPrinter>
Pistache::Http::Connection::connect(Pistache::Address const&)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 48 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
Pistache::Http::Private::Parser<Pistache::Http::Response>::Parser()
Pistache::Http::Connection::Connection()
void __gnu_cxx::new_allocator<Pistache::Http::Connection>::construct<Pistache::Http::Connection>(Pistache::Http::Connection*)
void std::allocator_traits<std::allocator>::construct<Pistache::Http::Connection>(std::allocator<Pistache::Http::Connection>&, Pistache::Http::Connection*)
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::Http::Connection, std::allocator>(std::_Sp_make_shared_tag, Pistache::Http::Connection*, std::allocator<Pistache::Http::Connection> const&)
std::__shared_ptr<Pistache::Http::Connection, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection>::shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::allocate_shared<Pistache::Http::Connection, std::allocator>(std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::make_shared<Pistache::Http::Connection>()
Pistache::Http::ConnectionPool::pickConnection(std::__cxx11::basic_string<char, std::char_traits, std::allocator> const&)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 32 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
__gnu_cxx::new_allocator<std::__detail::_Hash_node>::allocate(unsigned long, void const*)
std::allocator_traits<std::allocator>::allocate(std::allocator<std::__detail::_Hash_node>&, unsigned long)
std::__detail::_Hash_node<std::pair, false>* std::__detail::_Hashtable_alloc<std::allocator>::_M_allocate_node<std::pair>(std::pair<int, std::shared_ptr>&&)
std::pair<std::__detail::_Node_iterator, bool> std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_emplace<std::pair>(std::integral_constant<bool, true>, std::pair<int, std::shared_ptr>&&)
std::pair<std::__detail::_Node_iterator, bool> std::__detail::_Insert<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits, false>::insert<std::pair, void>(std::pair<int, std::shared_ptr>&&)
std::pair<std::__detail::_Node_iterator, bool> std::unordered_map<int, std::shared_ptr, std::hash, std::equal_to, std::allocator>::insert<std::pair, void>(std::pair<int, std::shared_ptr>&&)
Pistache::Http::Transport::asyncSendRequestImpl(Pistache::Http::Transport::RequestEntry const&, Pistache::Http::Transport::WriteStatus)
operator()
callAsync<long int, Pistache::Http::Transport::asyncSendRequest(std::shared_ptr, std::shared_ptr, std::__cxx11::string)::>
Promise<Pistache::Http::Transport::asyncSendRequest(std::shared_ptr, std::shared_ptr, std::__cxx11::string)::>
Pistache::Http::Transport::asyncSendRequest(std::shared_ptr<Pistache::Http::Connection>, std::shared_ptr<Pistache::TimerPool::Entry>, std::__cxx11::basic_string<char, std::char_traits, std::allocator>)
Pistache::Http::Connection::performImpl(Pistache::Http::Request const&, std::chrono::duration<long, std::ratio>, Pistache::Async::Resolver, Pistache::Async::Rejection, std::function<void ()>)
Pistache::Http::Connection::processRequestQueue()
operator()
doResolve
Pistache::Async::Private::Continuable<void>::resolve(std::shared_ptr<Pistache::Async::Private::Core> const&)
Pistache::Async::Resolver::operator()() const
Pistache::Http::Transport::onReady(Pistache::Aio::FdSet const&)
Pistache::Aio::SyncImpl::handleFds(std::vector<Pistache::Polling::Event, std::allocator>) const
Pistache::Aio::SyncImpl::runOnce()
Pistache::Aio::SyncImpl::run()
Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}::operator()() const
void std::__invoke_impl<void, Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>(std::__invoke_other, Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}&&)
std::__invoke_result<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>::type std::__invoke<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>(std::__invoke_result&&, (Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}&&)...)
decltype (__invoke((_S_declval<0ul>)())) std::thread::_Invoker<std::tuple>::_M_invoke<0ul>(std::_Index_tuple<0ul>)
std::thread::_Invoker<std::tuple>::operator()()
std::thread::_State_impl<std::thread::_Invoker>::_M_run()
(libstdc++.so.6+0x0000000bd57e)
Indirect leak of 24 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
__gnu_cxx::new_allocator<std::__detail::_Hash_node_base*>::allocate(unsigned long, void const*)
std::allocator_traits<std::allocator>::allocate(std::allocator<std::__detail::_Hash_node_base*>&, unsigned long)
std::__detail::_Hashtable_alloc<std::allocator>::_M_allocate_buckets(unsigned long)
std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_allocate_buckets(unsigned long)
std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_rehash_aux(unsigned long, std::integral_constant<bool, true>)
std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_rehash(unsigned long, unsigned long const&)
std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_insert_unique_node(unsigned long, unsigned long, std::__detail::_Hash_node<std::pair, false>*)
std::pair<std::__detail::_Node_iterator, bool> std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_emplace<std::pair>(std::integral_constant<bool, true>, std::pair<int, std::shared_ptr>&&)
std::pair<std::__detail::_Node_iterator, bool> std::__detail::_Insert<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits, false>::insert<std::pair, void>(std::pair<int, std::shared_ptr>&&)
std::pair<std::__detail::_Node_iterator, bool> std::unordered_map<int, std::shared_ptr, std::hash, std::equal_to, std::allocator>::insert<std::pair, void>(std::pair<int, std::shared_ptr>&&)
Pistache::Http::Transport::asyncSendRequestImpl(Pistache::Http::Transport::RequestEntry const&, Pistache::Http::Transport::WriteStatus)
operator()
callAsync<long int, Pistache::Http::Transport::asyncSendRequest(std::shared_ptr, std::shared_ptr, std::__cxx11::string)::>
Promise<Pistache::Http::Transport::asyncSendRequest(std::shared_ptr, std::shared_ptr, std::__cxx11::string)::>
Pistache::Http::Transport::asyncSendRequest(std::shared_ptr<Pistache::Http::Connection>, std::shared_ptr<Pistache::TimerPool::Entry>, std::__cxx11::basic_string<char, std::char_traits, std::allocator>)
Pistache::Http::Connection::performImpl(Pistache::Http::Request const&, std::chrono::duration<long, std::ratio>, Pistache::Async::Resolver, Pistache::Async::Rejection, std::function<void ()>)
Pistache::Http::Connection::processRequestQueue()
operator()
doResolve
Pistache::Async::Private::Continuable<void>::resolve(std::shared_ptr<Pistache::Async::Private::Core> const&)
Pistache::Async::Resolver::operator()() const
Pistache::Http::Transport::onReady(Pistache::Aio::FdSet const&)
Pistache::Aio::SyncImpl::handleFds(std::vector<Pistache::Polling::Event, std::allocator>) const
Pistache::Aio::SyncImpl::runOnce()
Pistache::Aio::SyncImpl::run()
Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}::operator()() const
void std::__invoke_impl<void, Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>(std::__invoke_other, Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}&&)
std::__invoke_result<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>::type std::__invoke<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>(std::__invoke_result&&, (Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}&&)...)
decltype (__invoke((_S_declval<0ul>)())) std::thread::_Invoker<std::tuple>::_M_invoke<0ul>(std::_Index_tuple<0ul>)
std::thread::_Invoker<std::tuple>::operator()()
std::thread::_State_impl<std::thread::_Invoker>::_M_run()
(libstdc++.so.6+0x0000000bd57e)
Indirect leak of 24 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
__gnu_cxx::new_allocator<std::__detail::_Hash_node_base*>::allocate(unsigned long, void const*)
std::allocator_traits<std::allocator>::allocate(std::allocator<std::__detail::_Hash_node_base*>&, unsigned long)
std::__detail::_Hashtable_alloc<std::allocator>::_M_allocate_buckets(unsigned long)
std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_allocate_buckets(unsigned long)
std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_rehash_aux(unsigned long, std::integral_constant<bool, true>)
std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_rehash(unsigned long, unsigned long const&)
std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_insert_unique_node(unsigned long, unsigned long, std::__detail::_Hash_node<std::pair, false>*)
std::pair<std::__detail::_Node_iterator, bool> std::_Hashtable<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits>::_M_emplace<std::pair>(std::integral_constant<bool, true>, std::pair<int, Pistache::Http::Transport::ConnectionEntry>&&)
std::pair<std::__detail::_Node_iterator, bool> std::__detail::_Insert<int, std::pair, std::allocator, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits, false>::insert<std::pair, void>(std::pair<int, Pistache::Http::Transport::ConnectionEntry>&&)
std::pair<std::__detail::_Node_iterator, bool> std::unordered_map<int, Pistache::Http::Transport::ConnectionEntry, std::hash, std::equal_to, std::allocator>::insert<std::pair, void>(std::pair<int, Pistache::Http::Transport::ConnectionEntry>&&)
Pistache::Http::Transport::handleConnectionQueue()
Pistache::Http::Transport::onReady(Pistache::Aio::FdSet const&)
Pistache::Aio::SyncImpl::handleFds(std::vector<Pistache::Polling::Event, std::allocator>) const
Pistache::Aio::SyncImpl::runOnce()
Pistache::Aio::SyncImpl::run()
Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}::operator()() const
void std::__invoke_impl<void, Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>(std::__invoke_other, Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}&&)
std::__invoke_result<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>::type std::__invoke<Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}>(std::__invoke_result&&, (Pistache::Aio::AsyncImpl::Worker::run()::{lambda()#1}&&)...)
decltype (__invoke((_S_declval<0ul>)())) std::thread::_Invoker<std::tuple>::_M_invoke<0ul>(std::_Index_tuple<0ul>)
std::thread::_Invoker<std::tuple>::operator()()
std::thread::_State_impl<std::thread::_Invoker>::_M_run()
(libstdc++.so.6+0x0000000bd57e)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
void std::vector<std::shared_ptr, std::allocator>::_M_realloc_insert<std::shared_ptr const&>(__gnu_cxx::__normal_iterator<std::shared_ptr*, std::vector>, std::shared_ptr<Pistache::Async::Private::Request> const&)
std::vector<std::shared_ptr, std::allocator>::push_back(std::shared_ptr<Pistache::Async::Private::Request> const&)
then<Pistache::Http::Connection::connect(const Pistache::Address&)::, Pistache::Http::ExceptionPrinter>
Pistache::Http::Connection::connect(Pistache::Address const&)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
Pistache::Http::Private::Parser<Pistache::Http::Response>::Parser()
Pistache::Http::Connection::Connection()
void __gnu_cxx::new_allocator<Pistache::Http::Connection>::construct<Pistache::Http::Connection>(Pistache::Http::Connection*)
void std::allocator_traits<std::allocator>::construct<Pistache::Http::Connection>(std::allocator<Pistache::Http::Connection>&, Pistache::Http::Connection*)
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::Http::Connection, std::allocator>(std::_Sp_make_shared_tag, Pistache::Http::Connection*, std::allocator<Pistache::Http::Connection> const&)
std::__shared_ptr<Pistache::Http::Connection, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection>::shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::allocate_shared<Pistache::Http::Connection, std::allocator>(std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::make_shared<Pistache::Http::Connection>()
Pistache::Http::ConnectionPool::pickConnection(std::__cxx11::basic_string<char, std::char_traits, std::allocator> const&)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
operator new(unsigned long)
Pistache::Http::Private::Parser<Pistache::Http::Response>::Parser()
Pistache::Http::Connection::Connection()
void __gnu_cxx::new_allocator<Pistache::Http::Connection>::construct<Pistache::Http::Connection>(Pistache::Http::Connection*)
void std::allocator_traits<std::allocator>::construct<Pistache::Http::Connection>(std::allocator<Pistache::Http::Connection>&, Pistache::Http::Connection*)
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<Pistache::Http::Connection, std::allocator>(std::_Sp_make_shared_tag, Pistache::Http::Connection*, std::allocator<Pistache::Http::Connection> const&)
std::__shared_ptr<Pistache::Http::Connection, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection>::shared_ptr<std::allocator>(std::_Sp_make_shared_tag, std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::allocate_shared<Pistache::Http::Connection, std::allocator>(std::allocator<Pistache::Http::Connection> const&)
std::shared_ptr<Pistache::Http::Connection> std::make_shared<Pistache::Http::Connection>()
Pistache::Http::ConnectionPool::pickConnection(std::__cxx11::basic_string<char, std::char_traits, std::allocator> const&)
Pistache::Http::Client::doRequest(Pistache::Http::Request, std::chrono::duration<long, std::ratio>)
Pistache::Http::RequestBuilder::send()
http_client_test_timeout_reject_Test::TestBody()
void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)
testing::Test::Run()
testing::TestInfo::Run()
testing::TestCase::Run()
testing::internal::UnitTestImpl::RunAllTests()
bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)
testing::UnitTest::Run()
RUN_ALL_TESTS()
main
__libc_start_main
knowledge4igor commented 5 years ago

Current status:

      Start  1: mime_test
 1/23 MemCheck  #1: mime_test ........................   Passed    1.81 sec
      Start  2: headers_test
 2/23 MemCheck  #2: headers_test .....................   Passed    2.58 sec
      Start  3: async_test
 3/23 MemCheck  #3: async_test .......................   Passed  179.78 sec
      Start  4: typeid_test
 4/23 MemCheck  #4: typeid_test ......................   Passed    1.37 sec
      Start  5: router_test
 5/23 MemCheck  #5: router_test ......................   Passed    4.05 sec
      Start  6: cookie_test
 6/23 MemCheck  #6: cookie_test ......................   Passed    1.91 sec
      Start  7: cookie_test_2
 7/23 MemCheck  #7: cookie_test_2 ....................   Passed    1.58 sec
      Start  8: cookie_test_3
 8/23 MemCheck  #8: cookie_test_3 ....................   Passed    3.82 sec
      Start  9: view_test
 9/23 MemCheck  #9: view_test ........................   Passed    1.47 sec
      Start 10: http_parsing_test
10/23 MemCheck #10: http_parsing_test ................   Passed    2.14 sec
      Start 11: http_uri_test
11/23 MemCheck #11: http_uri_test ....................   Passed    1.89 sec
      Start 12: http_server_test
12/23 MemCheck #12: http_server_test .................   Passed   34.80 sec
      Start 13: http_client_test
13/23 MemCheck #13: http_client_test .................   Passed    8.52 sec
      Start 14: net_test
14/23 MemCheck #14: net_test .........................   Passed    1.50 sec
      Start 15: listener_test
15/23 MemCheck #15: listener_test ....................   Passed    2.45 sec
      Start 16: payload_test
16/23 MemCheck #16: payload_test .....................   Passed   10.81 sec
      Start 17: streaming_test
17/23 MemCheck #17: streaming_test ...................   Passed   27.96 sec
      Start 18: rest_server_test
18/23 MemCheck #18: rest_server_test .................   Passed    5.16 sec
      Start 19: string_view_test
19/23 MemCheck #19: string_view_test .................   Passed    1.60 sec
      Start 20: mailbox_test
20/23 MemCheck #20: mailbox_test .....................   Passed    2.08 sec
      Start 21: stream_test
21/23 MemCheck #21: stream_test ......................   Passed    1.72 sec
      Start 22: reactor_test
22/23 MemCheck #22: reactor_test .....................   Passed    3.45 sec
      Start 23: https_server_test
23/23 MemCheck #23: https_server_test ................   Passed    8.10 sec

100% tests passed, 0 tests failed out of 23
dennisjenkins75 commented 5 years ago

Nice!

I'd like to leave this bug open until the unit tests include running memcheck.

Tachi107 commented 2 years ago

AddressSanitizer just discovered a memory leak in https://github.com/pistacheio/pistache/commit/f10ca8e3a0a7d30ec7692b93bc13b5202b464914

2022-08-19T15:27:38.5939528Z [ RUN ] http_server_test.client_multiple_requests_disconnection_on_timeout_from_single_threaded_server 2022-08-19T15:27:38.5950645Z [test] [7fcf1179c000] Trying to run server... 2022-08-19T15:27:38.5951724Z [server] [7fcf1179c000] Init Hello handler with 6 seconds delay 2022-08-19T15:27:38.5962945Z [test] [7fcf1179c000] Server address: localhost:40697 2022-08-19T15:27:39.6044888Z An exception occured: Timeout 2022-08-19T15:27:39.6045508Z [client] [7fcf0d1fe700] [0] Reject with reason: 2022-08-19T15:27:39.6050047Z [client] [7fcf0d1fe700] [1] Reject with reason: 2022-08-19T15:27:39.6054875Z [client] [7fcf1179c000] resolves: 0, rejects: 1, request timeout: 1 seconds, wait: 6 seconds 2022-08-19T15:27:39.6060180Z An exception occured: Timeout 2022-08-19T15:27:39.6063442Z ================================================================= 2022-08-19T15:27:39.6076372Z ==4729==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffd932c3770 at pc 0x0000004238a0 bp 0x7fcf0d1fb770 sp 0x7fcf0d1fb768 2022-08-19T15:27:39.6077695Z READ of size 4 at 0x7ffd932c3770 thread T6 2022-08-19T15:27:40.2460731Z #0 0x42389f in clientLogicFunc(unsigned long, std::__cxx11::basic_string, std::allocator > const&, int, int)::$_1::operator()(std::__exception_ptr::exception_ptr) const /__w/pistache/pistache/build/../tests/http_server_test.cc:223:17 2022-08-19T15:27:40.2463127Z #1 0x42107d in Pistache::Async::Private::impl::Continuation, std::allocator > const&, int, int)::$_0, clientLogicFunc(unsigned long, std::__cxx11::basic_string, std::allocator > const&, int, int)::$_1, void (Pistache::Http::Response)>::doReject(std::shared_ptr > const&) /__w/pistache/pistache/build/../include/pistache/async.h:529:21 2022-08-19T15:27:40.2467674Z #2 0x4c2c98 in Pistache::Async::Private::Continuable::reject(std::shared_ptr const&) /__w/pistache/pistache/build/../include/pistache/async.h:347:21 2022-08-19T15:27:40.2751876Z #3 0x7fcf12657613 in bool Pistache::Async::Rejection::operator()(std::runtime_error) const /__w/pistache/pistache/build/../include/pistache/async.h:919:22 2022-08-19T15:27:40.2892053Z #4 0x7fcf128d98f4 in Pistache::Http::Experimental::Connection::handleTimeout() /__w/pistache/pistache/build/../src/client/client.cc:705:13 2022-08-19T15:27:40.2896125Z #5 0x7fcf128d19bd in Pistache::Http::Experimental::Transport::handleReadableEntry(Pistache::Aio::FdSet::Entry const&) /__w/pistache/pistache/build/../src/client/client.cc:437:33 2022-08-19T15:27:40.2896899Z #6 0x7fcf128ce11c in Pistache::Http::Experimental::Transport::onReady(Pistache::Aio::FdSet const&) /__w/pistache/pistache/build/../src/client/client.cc:255:17 2022-08-19T15:27:40.2932145Z #7 0x7fcf1259db80 in Pistache::Aio::SyncImpl::handleFds(std::vector >) const /__w/pistache/pistache/build/../src/common/reactor.cc:205:34 2022-08-19T15:27:40.2932977Z #8 0x7fcf12594bf6 in Pistache::Aio::SyncImpl::runOnce() /__w/pistache/pistache/build/../src/common/reactor.cc:165:21 2022-08-19T15:27:40.2936841Z #9 0x7fcf1259522b in Pistache::Aio::SyncImpl::run() /__w/pistache/pistache/build/../src/common/reactor.cc:177:17 2022-08-19T15:27:40.2938546Z #10 0x7fcf125cb876 in Pistache::Aio::AsyncImpl::Worker::run()::'lambda'()::operator()() const /__w/pistache/pistache/build/../src/common/reactor.cc:515:27 2022-08-19T15:27:40.2941914Z #11 0x7fcf125cb521 in void std::__invoke_impl(std::__invoke_other, Pistache::Aio::AsyncImpl::Worker::run()::'lambda'()&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:60:14 2022-08-19T15:27:40.2945886Z #12 0x7fcf125cb321 in std::__invoke_result::type std::__invoke(Pistache::Aio::AsyncImpl::Worker::run()::'lambda'()&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:95:14 2022-08-19T15:27:40.2950177Z #13 0x7fcf125cb279 in void std::thread::_Invoker >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/thread:264:13 2022-08-19T15:27:40.2951945Z #14 0x7fcf125cb1c9 in std::thread::_Invoker >::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/thread:271:11 2022-08-19T15:27:40.2954973Z #15 0x7fcf125caf90 in std::thread::_State_impl > >::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/thread:215:13 2022-08-19T15:27:40.2985898Z #16 0x7fcf11ba1ecf (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xceecf) 2022-08-19T15:27:40.2992467Z #17 0x7fcf11ca8ea6 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x8ea6) 2022-08-19T15:27:40.3005346Z #18 0x7fcf1189adee in clone (/lib/x86_64-linux-gnu/libc.so.6+0xfddee) 2022-08-19T15:27:40.3006235Z 2022-08-19T15:27:40.3011166Z Address 0x7ffd932c3770 is located in stack of thread T0 at offset 1456 in frame 2022-08-19T15:27:40.3015402Z #0 0x3cd51f in clientLogicFunc(unsigned long, std::__cxx11::basic_string, std::allocator > const&, int, int) /__w/pistache/pistache/build/../tests/http_server_test.cc:196 2022-08-19T15:27:40.3016403Z 2022-08-19T15:27:40.3029985Z This frame has 23 object(s): 2022-08-19T15:27:40.3030702Z [32, 36) 'timeout_seconds.addr' 2022-08-19T15:27:40.3031344Z [48, 52) 'wait_seconds.addr' 2022-08-19T15:27:40.3032075Z [64, 312) 'client' (line 197) 2022-08-19T15:27:40.3032417Z [384, 408) 'ref.tmp' (line 198) 2022-08-19T15:27:40.3032772Z [448, 472) 'responses' (line 200) 2022-08-19T15:27:40.3033086Z [512, 872) 'rb' (line 201) 2022-08-19T15:27:40.3033388Z [944, 1304) 'ref.tmp2' (line 201) 2022-08-19T15:27:40.3033694Z [1376, 1384) 'agg.tmp' 2022-08-19T15:27:40.3034015Z [1408, 1416) 'ref.tmp5' (line 201) 2022-08-19T15:27:40.3034360Z [1440, 1444) 'resolver_counter' (line 202) 2022-08-19T15:27:40.3034851Z [1456, 1460) 'reject_counter' (line 203) <== Memory access at offset 1456 is inside this variable 2022-08-19T15:27:40.3035257Z [1472, 1528) 'response' (line 206) 2022-08-19T15:27:40.3035578Z [1568, 1624) 'agg.tmp.ensured' 2022-08-19T15:27:40.3035877Z [1664, 1680) 'agg.tmp13' 2022-08-19T15:27:40.3036171Z [1696, 1712) 'agg.tmp14' 2022-08-19T15:27:40.3036662Z [1728, 1784) 'sync' (line 228) 2022-08-19T15:27:40.3036958Z [1824, 1832) 'agg.tmp22' 2022-08-19T15:27:40.3037267Z [1856, 1864) 'agg.tmp25' 2022-08-19T15:27:40.3037598Z [1888, 1984) 'barrier' (line 229) 2022-08-19T15:27:40.3037930Z [2016, 2024) 'ref.tmp34' (line 230) 2022-08-19T15:27:40.3038280Z [2048, 2440) 'ref.tmp42' (line 234) 2022-08-19T15:27:40.3038629Z [2512, 2544) 'ref.tmp43' (line 234) 2022-08-19T15:27:40.3038957Z [2576, 2577) 'ref.tmp44' (line 234) 2022-08-19T15:27:40.3045095Z HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork 2022-08-19T15:27:40.3048852Z (longjmp and C++ exceptions *are* supported) 2022-08-19T15:27:40.3050204Z SUMMARY: AddressSanitizer: stack-use-after-scope /__w/pistache/pistache/build/../tests/http_server_test.cc:223:17 in clientLogicFunc(unsigned long, std::__cxx11::basic_string, std::allocator > const&, int, int)::$_1::operator()(std::__exception_ptr::exception_ptr) const 2022-08-19T15:27:40.3052052Z Shadow bytes around the buggy address: 2022-08-19T15:27:40.3071201Z 0x100032650690: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 2022-08-19T15:27:40.3071544Z 0x1000326506a0: f8 f8 f8 f8 f8 f2 f2 f2 f2 f2 f2 f2 f2 f2 f8 f8 2022-08-19T15:27:40.3071869Z 0x1000326506b0: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 2022-08-19T15:27:40.3072187Z 0x1000326506c0: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 2022-08-19T15:27:40.3072510Z 0x1000326506d0: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f2 f2 f2 f2 f2 2022-08-19T15:27:40.3072829Z =>0x1000326506e0: f2 f2 f2 f2 00 f2 f2 f2 f8 f2 f2 f2 f8 f2[f8]f2 2022-08-19T15:27:40.3073125Z 0x1000326506f0: f8 f8 f8 f8 f8 f8 f8 f2 f2 f2 f2 f2 00 00 00 00 2022-08-19T15:27:40.3073434Z 0x100032650700: 00 00 00 f2 f2 f2 f2 f2 00 00 f2 f2 00 00 f2 f2 2022-08-19T15:27:40.3073736Z 0x100032650710: f8 f8 f8 f8 f8 f8 f8 f2 f2 f2 f2 f2 00 f2 f2 f2 2022-08-19T15:27:40.3074312Z 0x100032650720: 00 f2 f2 f2 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 2022-08-19T15:27:40.3074604Z 0x100032650730: f2 f2 f2 f2 f8 f2 f2 f2 f8 f8 f8 f8 f8 f8 f8 f8 2022-08-19T15:27:40.3074977Z Shadow byte legend (one shadow byte represents 8 application bytes): 2022-08-19T15:27:40.3075321Z Addressable: 00 2022-08-19T15:27:40.3075609Z Partially addressable: 01 02 03 04 05 06 07 2022-08-19T15:27:40.3075910Z Heap left redzone: fa 2022-08-19T15:27:40.3076282Z Freed heap region: fd 2022-08-19T15:27:40.3076549Z Stack left redzone: f1 2022-08-19T15:27:40.3076817Z Stack mid redzone: f2 2022-08-19T15:27:40.3077086Z Stack right redzone: f3 2022-08-19T15:27:40.3077350Z Stack after return: f5 2022-08-19T15:27:40.3077625Z Stack use after scope: f8 2022-08-19T15:27:40.3077898Z Global redzone: f9 2022-08-19T15:27:40.3078151Z Global init order: f6 2022-08-19T15:27:40.3078422Z Poisoned by user: f7 2022-08-19T15:27:40.3078696Z Container overflow: fc 2022-08-19T15:27:40.3078962Z Array cookie: ac 2022-08-19T15:27:40.3079212Z Intra object redzone: bb 2022-08-19T15:27:40.3079482Z ASan internal: fe 2022-08-19T15:27:40.3079750Z Left alloca redzone: ca 2022-08-19T15:27:40.3080003Z Right alloca redzone: cb 2022-08-19T15:27:40.3080268Z Shadow gap: cc 2022-08-19T15:27:40.3080530Z Thread T6 created by T0 here: 2022-08-19T15:27:40.3080917Z #0 0x38599a in pthread_create (/__w/pistache/pistache/build/tests/run_http_server_test+0x38599a) 2022-08-19T15:27:40.3081886Z #1 0x7fcf11ba2144 in std::thread::_M_start_thread(std::unique_ptr >, void (*)()) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xcf144) 2022-08-19T15:27:40.3082531Z #2 0x7fcf125c9c13 in Pistache::Aio::AsyncImpl::Worker::run() /__w/pistache/pistache/build/../src/common/reactor.cc:509:26 2022-08-19T15:27:40.3083081Z #3 0x7fcf125bc4bb in Pistache::Aio::AsyncImpl::run() /__w/pistache/pistache/build/../src/common/reactor.cc:450:22 2022-08-19T15:27:40.3083738Z #4 0x7fcf125866f3 in Pistache::Aio::Reactor::run() /__w/pistache/pistache/build/../src/common/reactor.cc:613:35 2022-08-19T15:27:40.3084375Z #5 0x7fcf128f0a37 in Pistache::Http::Experimental::Client::init(Pistache::Http::Experimental::Client::Options const&) /__w/pistache/pistache/build/../src/client/client.cc:978:19 2022-08-19T15:27:40.3085126Z #6 0x3cdbff in clientLogicFunc(unsigned long, std::__cxx11::basic_string, std::allocator > const&, int, int) /__w/pistache/pistache/build/../tests/http_server_test.cc:198:12 2022-08-19T15:27:40.3085898Z #7 0x3d6b13 in http_server_test_client_multiple_requests_disconnection_on_timeout_from_single_threaded_server_Test::TestBody() /__w/pistache/pistache/build/../tests/http_server_test.cc:291:37 2022-08-19T15:27:40.3086722Z #8 0x65a846 in void testing::internal::HandleExceptionsInMethodIfSupported(testing::Test*, void (testing::Test::*)(), char const*) (/__w/pistache/pistache/build/tests/run_http_server_test+0x65a846) 2022-08-19T15:27:40.3087183Z 2022-08-19T15:27:40.3087278Z ==4729==ABORTING
kiplingw commented 2 years ago

My first impression is that there probably is a memory leak, but that it's not related in any material way to that PR. There was probably some kind of race condition that we might have finally gotten lucky so that it could reveal itself. My guess is when the timeout exceptions were thrown something wasn't cleaned up.