1

I use the reactor pattern in my C++ application. I use a thread vector std::vector <boost::thread> tvec {1000}; and an event queue boost::lockfree::queue <int> events {1000}; to handle events.

My event dispatcher looks like this:

void my_class::event_dispatcher (void)
{
    INFO << "started";

    int event_element = 0;

    try
    {
        while (true)
        {
            // 1. wait for an event
            for (;;)
            {
                if (events.pop (event_element)) break;  // returns true if the queue is not empty
                boost::this_thread::sleep (boost::posix_time::milliseconds (250));      
            }

            // 2. handle event
            switch (event_element)
            {
                // 1-20 ...
                case 21:
                {
                    tvec.at(21).interrupt();
                    tvec.at(21) = boost::thread (boost::bind(&my_class::write_units_court_a, this));
                    break;
                }
                // 21-999...
                default:
                {
                    WARNING << "INVALID EVENT = " << event_element;
                    break;
                }
            }   
        }
    }
    catch (const std::exception &e)
    {
        ERROR << "e.what() = " << e.what();
        return;
    }

    INFO << "ended";

    return;
}

My problem is that when I run pmap -x PROGRAM_PID it shows dozens of these lines:

00007f4063fd9000    8192      12      12 rw---   [ anon ]
00007f4063fd9000       0       0       0 rw---   [ anon ]
00007f40647d9000       4       0       0 -----   [ anon ]
00007f40647d9000       0       0       0 -----   [ anon ]
00007f40647da000    8192      16      16 rw---   [ anon ]
00007f40647da000       0       0       0 rw---   [ anon ]
00007f4064fda000       4       0       0 -----   [ anon ]
00007f4064fda000       0       0       0 -----   [ anon ]
00007f4064fdb000    8192      12      12 rw---   [ anon ]
00007f4064fdb000       0       0       0 rw---   [ anon ]
00007f40657db000       4       0       0 -----   [ anon ]
00007f40657db000       0       0       0 -----   [ anon ]

which I assume to be a memory leak from my event dispatcher creating and interrupting multiple threads as the program runs. I use boost logging in these threads and catch the interrupts in the threads properly; example:

void my_class::write_units_court_a (void)
{
    INFO << "started";

    try
    {
        // working code here ...
    }
    catch (const std::exception &e)
    {
        ERROR << "e.what() = " << e.what();     
        return;
    }
    catch (boost::thread_interrupted)
    {
        INFO << "interrupted";
        return;
    }

    INFO << "ended";

    return;
}

What is causing this seemingly thread memory leak? Valgrind shows memory lost and I can see the program use more memory as it starts and ends threads.

xinthose
  • 3,213
  • 3
  • 40
  • 59
  • Can you distill this into something self-contained? I'm not well versed in reading `pmap` so maybe you can elaborate a little bit on why you assume these are leaks – sehe Jan 11 '18 at 00:16
  • @sehe I assume they're leaks because of [this answer](https://stackoverflow.com/a/1483482/4056146). Tomorrow, I plan on trying `boost::shared_ptr thr` instead of a thread vector and see if that helps . I will report back. – xinthose Jan 11 '18 at 04:12

1 Answers1

1

I now use boost::shared_ptr <boost::thread> thr_ev_21; and

if (thr_ev_21.get()) thr_ev_21->interrupt();
thr_ev_21.reset(new boost::thread (boost::bind(&porter::write_units_court_a, this)));

Now my memory usage plateaus instead of constantly growing. The thread object must not be destroyed with this line on the second pass:

tvec.at(21) = boost::thread (boost::bind(&my_class::write_units_court_a, this));
xinthose
  • 3,213
  • 3
  • 40
  • 59