Конференция "Прочее" » Отловить завершение чужих потоков
 
  • Crysis © (18.05.16 18:42) [20]
    > NoUser ©   (18.05.16 17:50) [19]

    Ну какое значение имеет, даём мы кому-то кусок памяти или нет...
    Есть особенность использования. Если завершения всех потоков не получится отследить - я сделаю через SystemThreadEndProc для своих потоков и более сложный и медленный вариант для чужих. Но хочется универсально.
  • DayGaykin © (18.05.16 19:59) [21]
    Facepalm
  • NoUser © (18.05.16 20:05) [22]
    > Но хочется универсально.
    Сделай второй калбек (для зачистки), сделай свою длл-ку в которую "передай" его и там вызывай в момент DLL_THREAD_DETACH.
  • Rouse_ © (18.05.16 22:54) [23]

    > Crysis ©   (18.05.16 14:56) [16]
    > А можно поподробнее?
    > Подойдёт ли этот способ для потоков, созданных вне Delphi?

    Что значит "вне Delphi"?
    Так ты перехватишь создание нити в твоем приложении (за исключением случая CreateRemoteThread из другого процесса)
  • Crysis © (19.05.16 12:01) [24]
    > Rouse_ ©   (18.05.16 22:54) [23]

    Допустим я использую сторонний движок, будь то звуковая библиотека, физика, базы данных. Они написаны на другом языке программирования, исходников нет; зато известно, что они вызывают CreateThread и внутри потока дёргают мой калбек. "Перехват ZwCreateThread" поможет в данной ситуации или нет? Можно поподробнее, как перехватить?
  • Rouse_ © (19.05.16 16:04) [25]
    Поможет если будешь делать перехват сплайсингом делать.
    http://alexander-bagel.blogspot.ru/2013/01/intercept.html
    http://alexander-bagel.blogspot.ru/2013/05/intercept2.html
  • Crysis © (19.05.16 17:41) [26]
    Спасибо, буду пробовать!
  • han_malign © (19.05.16 17:48) [27]

    > решено поменять принципы обработки данных, задействуя threadvar
    > и кеширование данных/буферов

    - кеширование внешнего контекста в реентерабельной функции - нонсенс...
    А промежутоные буфера надо выделять на стеке(в пределах отведенных(по умолчанию) ~ 1Мб естественно)...
  • DayGaykin © (19.05.16 20:32) [28]

    > Rouse_ ©   (19.05.16 16:04) [25]

    А не проще перехватить импорт DLL?
  • Rouse_ © (19.05.16 20:37) [29]

    > DayGaykin ©   (19.05.16 20:32) [28]
    > А не проще перехватить импорт DLL?

    Он только для статической линковки, используется.
  • DayGaykin © (19.05.16 20:39) [30]

    > Rouse_ ©   (19.05.16 20:37) [29]

    Со сплайсингом в многопоточности точно не без проблем обойдется, да еще если на 64 битах запускать.
  • Rouse_ © (19.05.16 21:10) [31]
    Если правильно делать с использование хотпатча (атомарной замены 2 байт в области нопов  в прологе функции) - никаких проблем не будет. Этож штатный механизм.
  • Rouse_ © (19.05.16 21:17) [32]
    В частности в 64 битах делается воот так:

    Вот тело ZwCreateThread (адрес точки входа 77AFD890), перед ней идет пятибайтный длинный NOP

    77AFD88B: 0F 1F 44 00 00                            nop dword ptr [rax+rax+00h]
    77AFD890: B8 DB 3C 03 00                            mov eax, 00033CDBh
    77AFD895: 48 63 C0                                  movsxd rax, rax
    77AFD898: FF E0                                     jmp rax
    77AFD89A: C3                                        ret



    первым шагом делаем установку джампа в область длинного нопа,
    вторым шагом - атомарно (через LOCK XCHG) джамп на эту область вместо инструкции JMP RAX (для других функций вместо него будет SYSCALL)
  • DayGaykin © (20.05.16 03:33) [33]

    > Rouse_ ©   (19.05.16 21:10) [31]
    > Если правильно делать с использование хотпатча (атомарной
    > замены 2 байт в области нопов  в прологе функции) - никаких
    > проблем не будет. Этож штатный механизм.

    Если я правильно помню, условия хот-патча не выполняются если программа запущена в 64хбитной ос.
  • Leonid Troyanovsky © (20.05.16 08:40) [34]

    > Leonid Troyanovsky ©   (18.05.16 14:02) [15]

    Вот набросал пример, без всякой оптимизации и контроля ошибок.

    type
      TMItem = packed record
        ThreadId: Cardinal;
        OTHandle: THandle;
        Data: DWord;
      end;
      PMItem = ^TMItem;

    var
     ftl: TThreadList;

    function GetDataPtr: PDWord;
    var
     i: Longint;
     pmi: PMItem;
     exCode: Cardinal;
    begin
     Result := nil;
     with ftl.LockList do
       try
         for i:= Count-1 downto 0 do
           begin
             pmi := PMItem(List[i]);
             if pmi.ThreadId = GetCurrentThreadId then
               begin
                 Result := @pmi.Data;
                 Continue;
               end;

             GetExitCodeThread(pmi.OTHandle, exCode);
             if ExCode <> STILL_ACTIVE then
               begin
                 OutputDebugString(PChar(IntToStr(ExCode)));
                 CloseHandle(pmi.OTHandle);
                 Dispose(pmi);
                 Delete(i);
               end;
           end;

         if Result = nil then
           begin
             New(pmi);
             pmi.ThreadId := GetCurrentThreadId;
             DuplicateHandle( GetCurrentProcess,
                              GetCurrentThread,
                              GetCurrentProcess,
                              @pmi.OTHandle,
                              0,
                              False,
                              DUPLICATE_SAME_ACCESS);
             pmi.Data := 0;
             Add(pmi);
             Result := @pmi.Data;
           end;
       finally
         ftl.UnlockList;
       end;
    end;

    type
     TMyThread = class(TThread)
       procedure Execute; override;
     end;

    procedure TMyThread.Execute;
    var
     pData: PDWord;
    begin
     pData := GetDataPtr;
     pData^ := Random(10000);
     Sleep (pData^);
     ReturnValue := pData^;
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
     ftl := TThreadList.Create;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
     TMyThread.Create(False).FreeOnTerminate := True;
    end;


    Смотрим в EventLog.

    --
    Regards, LVT.
  • Rouse_ © (20.05.16 09:13) [35]

    > DayGaykin ©   (20.05.16 03:33) [33]
    > Если я правильно помню, условия хот-патча не выполняются
    > если программа запущена в 64хбитной ос.

    Все выполняется иначе как бы перехваты в моем софте работали?
  • Rouse_ © (20.05.16 09:37) [36]
    А, или ты про 32 битный софт в 64 битной ОС? Да, там некоторые функции идут без пролога, но там тоже можно пошаманить
  • DayGaykin © (20.05.16 13:32) [37]

    > Rouse_ ©   (20.05.16 09:37) [36]
    > А, или ты про 32 битный софт в 64 битной ОС? Да, там некоторые
    > функции идут без пролога, но там тоже можно пошаманить

    Да-да. Ты мне про это, кстати, и говорил.
  • Cobalt © (25.05.16 11:53) [38]
    Почему бы не поменять способ работы на что-то типа
    BeginUpdate;
    EndUpdate;


    ?
 
Конференция "Прочее" » Отловить завершение чужих потоков
Есть новые Нет новых   [134433   +22][b:0][p:0.004]