C ++ Boost threadgroup.interrupt_all () вызывая выход из основного потока тоже

0

Я использую приведенный ниже код для создания потоков и добавления их в пул потоков. Потоки загружаются нормально, и каждый из них выполняет простую процедуру циклизации до тех пор, пока основной поток не вызовет 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;

}
  • 0
    Не могли бы вы опубликовать небольшую версию основного и потокового задания, которое демонстрирует поведение? Есть несколько вещей, которые могут происходить на сайте, с которого вы вызываете эту функцию, или в самом цикле потока после вызова прерывания, что может вызвать проблемы.
  • 0
    Дополнительный код был размещен, спасибо.
Показать ещё 1 комментарий
Теги:
multithreading
boost

2 ответа

0
Лучший ответ

У вас есть ошибка здесь:

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

Вы создаете локальный объект tWorker который удаляется сразу после вызова add_thread(). Так vecThreads содержит висячие указатели на thread с. Когда вы вызываете 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().

  • 0
    Я внес коррективы в отношении указателя, но теперь я сталкиваюсь с новой ошибкой, вызываемой после завершения вызова экземпляра 'boost :: exception_detail :: clone_impl <boost :: exception_detail :: error_info_injector <boost :: thread_resource_error>>' what (): boost thread: попытка присоединения
  • 0
    @ user246181 Пожалуйста, попробуйте переместить объявление http::client client; изнутри блока try . Таким образом, код должен быть http::client client; try {...} вместо try{ http::client client; ...}
Показать ещё 7 комментариев
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.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню