Конференция "Прочее" » Отловить завершение чужих потоков
 
  • Crysis © (17.05.16 16:43) [0]
    Вопрос знатокам WinAPI (и желательно POSIX)

    В произвольное время разные потоки дёргают мою функцию. Причём потоки могут быть созданы в отдельном Dll кем угодно.
    В момент вызова функции я могу получить CurretThreadId.
    Необходимо, зная эти ThreadId, навесить на потоки какой-нибудь калбек, который будет вызываться после завершения потока. С эксепшном или в штатном режиме.
    Каким образом?

    Опережая вопрос "зачем тебе это".
    Есть несколько мультипоточных высоконагруженных проектов. Причём бывает потоки создаются в сторонней Dll.
    Было решено поменять принципы обработки данных, задействуя threadvar и кеширование данных/буферов.
    Но беда в том, что threadvar-области не финализируются при завершении потока.
    Тот же TParallel постоянно создаёт и удаляет потоки, а у нас течёт память, причём серьёзно.
  • Pavia © (17.05.16 19:18) [1]
    Вешаешь Хук на EndThread
  • Crysis © (17.05.16 20:21) [2]
    Как?
    Сработает ли это на потоки, которые созданы вне Delphi?
  • DayGaykin © (17.05.16 21:43) [3]
    Создаешь свой поток-следилку и там делаешь:
    OpenThread+WaitForSingleObject.

    Чтобы следить сразу за несколькими потоками: WaitForMultipleObjects и алгоритм посложнее. Тут можно добавить еще Event, чтобы можно было прерывать WaitForMultipleObjects и обновлять список слежения.

    Чтобы следить за более чем MAXIMUM_WAIT_OBJECTS потоками, необходимо создать несколько потоков-следилок.
  • Crysis © (17.05.16 22:39) [4]
    > DayGaykin ©   (17.05.16 21:43) [3]

    Такой подход наверное тоже некорректен.
    Калбек по идее должен вызываться в завершающемся потоке. Потому что нужен доступ к TLS.
    В предложенном тобой варианте - я его не увижу.
  • NoUser © (18.05.16 00:03) [5]
    DLL_THREAD_DETACH


    >  который будет вызываться после завершения потока
    в том же потоке.
  • Crysis © (18.05.16 00:06) [6]
    > NoUser ©   (18.05.16 00:03) [5]

    Но у меня же не Dll
    Точнее не обязательно Dll
  • NoUser © (18.05.16 00:19) [7]
    PS.
    > Было решено поменять принципы обработки

    А если у потока после работы с функцией еще много планов на дальнейшую жизнь, то 'ваша' память будет ему в подарок?
  • NoUser © (18.05.16 00:23) [8]
    > Но у меня же не Dll
    ну, добавьте ещё и dll
  • DayGaykin © (18.05.16 00:27) [9]

    > Crysis ©   (17.05.16 22:39) [4]
    > > DayGaykin ©   (17.05.16 21:43) [3]
    >
    > Такой подход наверное тоже некорректен.
    > Калбек по идее должен вызываться в завершающемся потоке.
    >  Потому что нужен доступ к TLS.
    > В предложенном тобой варианте - я его не увижу.

    Тогда нормально никак.

    Можно, конечно извратиться так:
    Перехватываешь createthread своего процесса. Вместо точки входа указываешь свою функцию, которая: навесит SEH фрейм и перейдет по исходной точке входа. А дальше должно быть понятно, если знать что такое SEH фрейм.
  • Crysis © (18.05.16 00:28) [10]
    > А если у потока после работы с функцией еще много планов
    > на дальнейшую жизнь, то 'ваша' память будет ему в подарок?


    В том то и дело
    "В подарок" только на время работы. А по завершению потока - память надо грамотно забрать.
  • Crysis © (18.05.16 00:30) [11]
    > Перехватываешь createthread своего процесса. Вместо точки
    > входа указываешь свою функцию, которая: навесит SEH фрейм
    > и перейдет по исходной точке входа. А дальше должно быть
    > понятно, если знать что такое SEH фрейм.


    Тогда уж не CreateThread, а ExitThread
    Но я боюсь, Касперский заблокирует наш софт у клиентов. Или иные антивирусы будут ругаться.
  • DayGaykin © (18.05.16 00:32) [12]

    > Crysis ©   (18.05.16 00:30) [11]

    В ExitThread может и не настать.


    > Но я боюсь, Касперский заблокирует наш софт у клиентов.
    > Или иные антивирусы будут ругаться.

    В своем процессе ты можешь делать что хочешь.
  • Rouse_ © (18.05.16 12:00) [13]
    Тогда лучше ZwCreateThread перехватить и там свою потоковую процедуру с SEH.
  • Leonid Troyanovsky © (18.05.16 13:27) [14]

    > Crysis ©   (17.05.16 16:43)

    >  Причём бывает потоки создаются в сторонней Dll.Было решено
    > поменять принципы обработки данных, задействуя threadvar
    > и кеширование данных/буферов.Но беда в том, что threadvar-
    > области не финализируются при завершении потока.

    threadvar - здесь костыль.

    Если какому-либо потоку нужны приватные данные, то он может
    распределить память и передать твоей функции указатель на нее.
    Перед завершением работы он должен ее освободить.

    В случае если код потоков менять нельзя, то память для
    потоков может выделять твоя функция, при условии, что
    один (или более поток) приложения будет следить путем
    WaitForMultipleObjects за рабочими и по их завершении
    освобождать связанную с ними память.

    Про синхронизацию доступа к общим ресурсам промолчу,
    бо, с этим, наверное, все в порядке.

    --
    Regards, LVT.
  • Leonid Troyanovsky © (18.05.16 14:02) [15]

    > Leonid Troyanovsky ©   (18.05.16 13:27) [14]

    > будет следить путем WaitForMultipleObjects за рабочими и
    > по их завершении освобождать связанную с ними память.

    Схему можно упростить до следующей:

    Функция ведет список (ThreadList) троек: ThreadId,
    OTHandle(хендл OpenThread),
    Data(указ. на распред. память).

    Когда список (или память) переполнится, проходим по списку,
    проверяем состояние OTHandle (f.e., GetThreadExitCode),
    утилизируем память, CloseHandle, удаляем лишнее.

    --
    Regards, LVT.
  • Crysis © (18.05.16 14:56) [16]
    > Rouse_ ©   (18.05.16 12:00) [13]
    > Тогда лучше ZwCreateThread перехватить и там свою потоковую
    > процедуру с SEH.


    А можно поподробнее?
    Подойдёт ли этот способ для потоков, созданных вне Delphi?
  • NoUser © (18.05.16 17:14) [17]
    > А можно поподробнее?
    Лучше расскажи/покажи как это "созданные кем угодно в отдельном Dll" потоки дёргают функцию в твоём exe ?
  • Crysis © (18.05.16 17:33) [18]
    > NoUser ©   (18.05.16 17:14) [17]

    А что удивительного? Передаётся калбек, он вызывает в отдельных потоках.
  • NoUser © (18.05.16 17:50) [19]
    > Передаётся калбек
    И что, внутри калбека каждому "новенькому" потоку даруется безвозмездно кусок памяти? - хорошенький "принцип обработки данных" !
 
Конференция "Прочее" » Отловить завершение чужих потоков
Есть новые Нет новых   [134433   +22][b:0][p:0.001]