Войти
ПрограммированиеФорумОбщее

[C++] Как прервать зависший поток?

Страницы: 1 2 3 Следующая »
#0
19:27, 10 мар 2023

собсно, сам минимальный тест:

#include <iostream>

void user_main(int argc, char ** argv)
{
    int cnt = 1;

    // код пользователя
    while(true)
    {
        ///-----------------|
        /// Бобик сдох...   |
        ///-----------------|

        std::cout << "\r" << ++cnt;
    }
}

#include <boost/thread.hpp>
#include <boost/chrono.hpp>


void foo(int argc, char ** argv)
{
    boost::chrono::microseconds maxduration{5'000'000};

    using namespace boost::chrono;
    auto start = high_resolution_clock::now();

    auto elapsed_times = [&start]()
    {   auto finish = high_resolution_clock::now();
        std::cout << "Elapsed time: " << std::fixed
                  << float(duration_cast<microseconds>(finish - start).count())
                   / 1'000'000 << " s\n";
    };

    boost::thread work(
        [] (int argc, char ** argv) -> void
        {
            user_main(argc, argv);
        }
        , argc
        , argv
    );
    if(work.try_join_for(maxduration))
    {
        elapsed_times ();
    }
    else
    {
        elapsed_times ();
        std::cout << "Time Limit Exceeded\n";

        work.interrupt(); ///<—- ???
    }
}

int main(int argc, char ** argv)
{   foo (    argc,         argv);

    std::cout << "PROGRAMM GOOD FINISHED\n";

    /// зависший поток продолжает кутить ...

    std::cin.get(); 
}

???

#1
19:39, 10 мар 2023

Получить нативный хэндл и вызвать Terminate из winapi, или любой подобный способ, ничего лучше нет

#2
(Правка: 19:48) 19:45, 10 мар 2023

/A\
> Получить нативный хэндл и вызвать Terminate из winapi, или любой подобный
> способ, ничего лучше нет
так чо я спрашиваю, неужто хвалённый буст это не умеет?

а Terminate не накроет основной поток вместе с зависшим???

я мог такой детач и в std сделать(или уже давно сделал).
нафиг тогда буст мне был нужен(((

#3
(Правка: 20:22) 19:57, 10 мар 2023

xlat-code
> неужто хвалённый буст это не умеет?
буст умеет, ты не умеешь
вот тут целый набор способов, но почему-то виндовый TerminateThread() проигнорирован
https://habr.com/ru/post/306332/

ну и вот это пять
xlat-code
> // код пользователя
> while(true)
> {

чего бы не сделать?

volatile bool m_run;

внутри класса с функтором, который ставить в false перед join()

#4
20:27, 10 мар 2023

#!
> чего бы не сделать?
длл с плагинами будут городить все кто сможет и захочет.

и мало ли что они там нагородят?

#!
> внутри класса с функтором, который ставить в false перед join()
это если бы я целиком писал, то да.

#5
(Правка: 20:50) 20:46, 10 мар 2023

xlat-code
> длл с плагинами будут городить все кто сможет и захочет
дочерний процесс сделай, с которым общаться по stdin/stdout
а то вдруг segfault ошибок там налепят, и уронят вообще всё, а так можно будет перезапустить

ещё можно над скриптосистемой подумать

#6
21:01, 10 мар 2023

#!
+1

#7
21:36, 10 мар 2023

xlat-code
> длл с плагинами будут городить все кто сможет и захочет.
> и мало ли что они там нагородят?
И ты теперь собираешься прибивать поток, который создала чужая длл с плагином? А как ты будешь понимать завис поток, или всё еще работает?

#8
22:15, 10 мар 2023

MrShoor
2)увеличивать глобальный счетчик. такой софтверный ватчдог будет. если этот поток конечно имеет вход в твою функцию.

у меня вот проблема была с шелл функцией открывающей диалог выбора файлов. она иногда зависала. видимо у меня в винде какие то косяки или расширения - компоненты в системы стоят корявые, которые за показ миниатюр отвечают.
не получилось даже вызывать ее в отдельном потоке. потому что там создается системный поток который все равно замораживает основной тред процесса. я даже не понял как так =/
а попытка убить дочерний поток с диалогом автоматически схлопывает процесс.

#9
23:11, 10 мар 2023

Noir
> 2)увеличивать глобальный счетчик. такой софтверный ватчдог будет. если этот
> поток конечно имеет вход в твою функцию.
Так а вход в твою функцию никак не поможет? Ну вот вошел поток в твою функцию, вышел... и? Завис поток или нет?

> у меня вот проблема была с шелл функцией открывающей диалог выбора файлов. она
> иногда зависала.
Вангую что проблема была как-то связана с твоим оконным циклом. Дело в том, что все диалоги винды начинают крутить оконный цикл внутри себя, т.е. вызываешь ты ShowDialog а там внутри:

procedure ShowDialog;
begin
  while GetMessage(msg)
  begin
  end;
end;

Т.е. например теперь все твои обработчики WM_PAINT будут вызываться изнутри ShowDialog-а.

И есть еще один подводный камень. WM_PAINT почему-то имеет более высокий приоритет чем WM_TIMER (что на мой взгляд - огромная промашка видны). Поэтому пока у тебя в очереди WM_PAINT, то WM_TIMER не обработается. А системные диалоги как раз занимаются тем, что создают таймер.

#10
23:20, 10 мар 2023

#!
> volatile
Только не волатайл, а атомик.

#11
(Правка: 23:44) 23:35, 10 мар 2023

Имбирная Ведьмочка
> а атомик
а разве volatile не строже чем atomic memory_order::relaxed?

partial write на одном bool вроде как не страшен, и писатель ровно один
в общем навскидку не припоминаю проблем с выходом приложения

#12
(Правка: 0:14) 0:10, 11 мар 2023

MrShoor
не. я пытался вызвать это в отдельном потоке. но зависание диалога все равно приводила к печальном концу приложения. кароче это ниче не поменяло.
если диалог созданный GetOpenFileName(ofn) зависал на отображении миниатюр то все.
приложение не отвечает. ваще похрен что попытка была в другом треде) создаваемый системой поток на выбор картинки каким то образом овладевает главным потоком процесса. либо заворачивает его туда самого (и это очень дерзко с его стороны!).

procedure TOpenPictureThread.Execute;
var
  ofn: TOpenFilename;
  buffer: array [0..MAXSIZE-1] of Char;
  OutString: string;
  dwerr:DWORD;
begin
 try
        fillchar(ofn,sizeof(ofn),0);
        fillchar(buffer,sizeof(buffer),0);
        ofn.lStructSize := SizeOf(ofn);
        ofn.hWndOwner := FOwner;
        ofn.hInstance := HInstance;
        ofn.lpstrFilter := NFilter;
        ofn.lpstrFile := buffer;
        ofn.nMaxFile := MAXSIZE;
        ofn.Flags := OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or
                      OFN_EXPLORER or OFN_HIDEREADONLY;
        ofn.lpstrTitle := OurTitle;
        if GetOpenFileName(ofn) then
        begin
          OutString := OutString + FullPathName + ofn.lpstrFile + #13#10;
          OutString := OutString + FullName + ExtractFileName(ofn.lpstrFile) + #13#10;
          OutString := OutString + FullName + ExtractFileExt(ofn.lpstrFile);
          if assigned(FOpenPictureCallback)then begin
            FResult:= ofn.lpstrFile;
            Synchronize(ThreadProc);
          end;
        end else begin
          dwerr:=CommDlgExtendedError;
          if dwerr<>0 then showmessage('error dialog create : '+ErrorToS(dwerr));
        end;
 except
  on E:exception do showmessage('error ' + e.Message);
 end;

end;
#13
4:48, 11 мар 2023

Noir
> если диалог созданный GetOpenFileName(ofn) зависал на отображении миниатюр то
> все.
> приложение не отвечает.
Очень странно, что приложение не отвечает, т.к. этот диалог используется во многих приложениях. При этом отображение миниатюр - это посути часть общего проводника. Ну т.е. с большой вероятностью у тебя бы сам проводник зависал.

#14
(Правка: 8:59) 8:57, 11 мар 2023

Прибивание потока не завершает те операции, которые он там у себя выполнял. Как правило, это создает проблемы, а не решает их. Операция крайне не рекомендована к использованию. Система просто снимает его с выполнения, а что у него внутри ей по барабану. Если просто намусорит по памяти, это еще малая беда, как правило последствия хуже.
Хочешь завершить поток? Попроси его самого завершиться.

Страницы: 1 2 3 Следующая »
ПрограммированиеФорумОбщее