C ++ boost thread group.interrupt all()导致主线程退出顶部

时间:2014-01-03 01:24:44

标签: c++ multithreading boost

我正在使用以下代码创建线程并将它们添加到线程池中。线程加载正常,每个执行一个简单的循环例程,直到主线程第二次调用ResetWorkerThreads并终止子线程。子线程被中断,但主线程也退出。没有错误写入控制台。我无法绕过它,因为它似乎没有任何异常,并且主线程尚未添加到vecThreads线程池中。此功能第二次全部“全部线程被杀”也不会输出,就好像它永远不会到达那一点。

std::string strPreviousSettings = "0";
std::string strPreviousAgentSettings = "0";
bool boolResetWorkers;
std::string strIP;
std::string strMACAddress;
boost::thread_group vecThreads;

std::string GetIP()
{

    std::string strIP;

    try
    {
        using namespace boost::network;

        std::string strRequest;
        http::client client;

        http::client::request request("http://test.com/ip.php");
        http::client::response response = client.get(request);
        strIP = body(response);




    }
    catch(...)
    {
        cout << "GetLocalIP - Error: " << endl;
    }

    return strIP;
}


std::string getMacAddress()
{
    std::string strMACAddress = GetFileContents("/sys/class/net/eth0/address");
    boost::replace_all(strMACAddress, ":", "");
    boost::replace_all(strMACAddress, "\n", "");
    return strMACAddress;
}


void ThreadSettingsWorker()
{
    int x = 1;
    strIP = GetIP();
    strMACAddress = getMacAddress();

    do {
        CheckEventSettings();
        CheckAgentSettings();

        if(boolResetWorkers==true)
        {
            ResetWorkerThreads();
        } else {
            boost::this_thread::sleep(boost::posix_time::milliseconds(3000));
        }


    } while ( x != 0 );
}

void ResetWorkerThreads()
{
    cout << "Resetting Workers Threads\n";
    boolResetWorkers = false;
    int intWorkerCount = 10; //Spawn 10 workers
    int X = 0;
    int intI = 1;

    cout << "Kill All Threads\n";

    try
    {
        vecThreads.interrupt_all();
    }
    catch(...)
    {
        //std::cerr << "Kill All Threads: " << std::endl;
    }

    cout << "All Threads Killed\n";


    for (int i = 0; i < intWorkerCount; ++i)
    {
        cout << "Starting Worker: " << (i + 1) << "\n";
        boost::thread tWorker(&ThreadWorker, (i + 1));
        vecThreads.add_thread(&tWorker);
    }




}


void TestRequest()
{
    try
    {
        using namespace boost::network;
        std::stringstream ss;
        http::client client;
        ss << "http://test.com/sadasdasd.html";
        http::client::request request(ss.str());
        http::client::response response = client.get(request);
        std::string strOutput = body(response);

        cout << "Test Request Out: " << strOutput << "\n";



    }
    catch(...)
    {
        cout << "TestRequest - Error: " << endl;
        return;
    }
}



void ThreadWorker(int intThread)
{
    try
    {
        int X = 0;

        do {
            cout << "Thread " << intThread << "\n";
            TestRequest();
        } while ( X != 55 );
    }
    catch(...)
    {

    }
}



void CheckEventSettings()
{

    try
    {
        using namespace boost::network;

        std::string strRequest;
        http::client client;
        http::client::request request("http://test.com/events.php");
        http::client::response response = client.get(request);
        std::string strOutput = body(response);


        if(strPreviousSettings==strOutput)
        {
            cout << "No Event Settings Changes\n";
        } else {

            cout << "Applying New Event Settings\n";
            strPreviousSettings = strOutput;
            std::string strDividerLine = "<br>";
            std::string strDividerField = "<field>";
            std::vector<std::string> vEvents;

            vEvents = EasySplit(strOutput, strDividerLine);

            for(std::vector<std::string>::const_iterator iEvent = vEvents.begin(); iEvent != vEvents.end() - 1; ++iEvent) { 

            }


        }



    }
    catch(...)
    {
        cout << "CheckEventSettings - Error: " << endl;
        return;
    }
}




void CheckAgentSettings()
{

    try
    {
        using namespace boost::network;
        std::stringstream ss;
        http::client client;
        ss << "http://test.com/checksettings.php";
        http::client::request request(ss.str());
        http::client::response response = client.get(request);
        std::string strOutput = body(response);

        if(strPreviousAgentSettings==strOutput)
        {
            cout << "No Agent Settings Changes\n";
        } else {
            cout << "Applying New Agent Settings\n";
            strPreviousAgentSettings = strOutput;
            boolResetWorkers = true;
        }



    }
    catch(...)
    {
        cout << "CheckAgentSettings - Error: " << endl;
        return;
    }
}




int main()
{


    // Start thread
    boost::thread tCheckSettings(&ThreadSettingsWorker);


    // Ask thread to stop
    //tCheckSettings.interrupt();

    // Join - wait when thread actually exits
    tCheckSettings.join();



    return 0;

}

2 个答案:

答案 0 :(得分:0)

您在此处有错误:

boost::thread tWorker(&ThreadWorker, (i + 1));
vecThreads.add_thread(&tWorker);

您创建一个本地对象tWorker,在调用add_thread()后删除该对象。所以vecThreads包含了thread s的悬空指针。当您调用vecThreads.interrupt_all()时,您会收到未定义的行为,因为vecThreads尝试访问已删除的thread对象,并且我认为您的程序因访问冲突或其他原因而终止。

您必须将代码更改为以下内容:

boost::thread* ptWorker = new boost::thread(&ThreadWorker, (i + 1));
vecThreads.add_thread(ptWorker);

请注意,您自己不需要delete这些thread个对象。 thread_group delete他们自己。

<强>此外:
terminate()的问题可能是http::client抛出异常的析构函数引起的。请尝试这样做,以便在TestRequest()

中消除这个问题
try{
    http::client client;
    try{
        // other code
    }
    catch (){}
}
catch(){}

我还建议在vecThreads之后重置interrupt_all()。例如,您可以将其定义为boost::scoped_ptr,然后在调用pvecThreads.reset(new boost::thread_group())后执行interrupt_all()
目前,中断的线程在中断后仍然保留在thread_group中,然后您再次尝试interrupt它们以及稍后thread_group中添加到ResetWorkerThreads()的新线程。

答案 1 :(得分:0)

ResetWorkerThreads内部你有:

for (int i = 0; i < intWorkerCount; ++i)
{
    cout << "Starting Worker: " << (i + 1) << "\n";
    // One issue is here, don't create a thread on the stack
    // and pass it to the thread group use new instead!
    boost::thread tWorker(&ThreadWorker, (i + 1));
    vecThreads.add_thread(&tWorker);
}

您正在将在堆栈上创建的线程添加到线程组。一旦遍历循环,线程内存就会失效。您将需要new线程并将该指针传递给add_thread。