Отследить удаление потока

Тема в разделе "WASM.WIN32", создана пользователем DevilDevil, 31 май 2020.

  1. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Допустим, какой-то поток (не известно, где создан) вызвал мою функцию
    Как отследить его завершение (желательно аварийное тоже) минимальными усилиями?
    Желательно для главного потока делать такую же логику. Фоновых потоков желательно не создавать

    В POSIX это делается макросом pthread_cleanup_push
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Не совсем понимаю задачу. Если просто нужно получить факт того, что поток завершился, то можно получить его хендл и ждать на WaitForSingleObject. Если нужно предотвратить аварийное завершение потока, то в той твоей функции поставить обработчик SEH. Если нужно предотвратить штатное завершение потока, то можно похукать ExitThread.
     
  3. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Хукать нельзя. Приложение должно работать в Windows Services, а там вроде хуки не проходят. Если очень упрощено - задача в том, чтобы инициализировать и финализировать TLS переменные корректно. WaitForSingleObject нужно делать в другом потоке, хотелось бы обойтись без использования дополнительных потоков.
     
  4. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Чего-чего? С этого момента поподробнее.
     
  5. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Я экспериментировал с хуками, в обычно приложении они работают, а в сервисах нет
    Не хотелось бы акцентировать на этом внимание

    Кстати в Dll есть калбеки с DLL_THREAD_DETACH
    Хотелось бы иметь что-то подобное
     
  6. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Этот колбек будет вызван только, если поток выйдет нормально, без эксепшена.
    --- Сообщение объединено, 1 июн 2020 ---
    Такое бывает, когда хуки сделаны кривыми руками.
     
    sn0w нравится это.
  7. hiddy

    hiddy Member

    Публикаций:
    0
    Регистрация:
    10 мар 2019
    Сообщения:
    82
  8. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    875
    Используй FLS. Там есть механизм колбеков. Пример на VB6.
     
  9. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Поток завершается ядром, это значит что никаких событий в процессе не происходит(на стороне юмод). Если поток крэшнул - возникло исключение, то работает стандартный механизм ловушек. Если он пал в глобальных крит структурах, то процесс вообще работать не может, его прикончит ядро и никаких сообщений не будет.
     
    Aiks нравится это.
  10. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Совершенно верно, это абсолютно то, что нужно!
    Только у меня не VS, у меня модуль компилируется в Clang, а линкуется в Delphi/FreePascal

    Тут наверное может быть две траблы:
    1. Не нахожу аналогичный код для Clang/GCC, подскажете, как это там выглядит? Пробовал такое, не сработало:
    Код (Text):
    1. #pragma data_seg(".CRT$XLY")
    2. void* p_thread_callback = my_tls_callback;
    3. #pragma data_seg()
    2. В теории можно получить объектники для Win32/64 в той же студии, но Delphi/FreePascal может не прилинковать эти секции. Судя по коду там нужно линкеру явно указать какие-то опции. Может протестируем этот сценарий? Соберите, пожалуйста, кто-нибудь объектник для Win64, который будет вызывать внешнюю функцию tls_test() без аргументов.
    --- Сообщение объединено, 1 июн 2020 ---
    Судя по описанию может подойти. Только смущает:
    1. Нужно переводить поток в Fiber
    2. Связываться с COM
    3. Появилась в винде относительно недавно

    "Стандартная" финализация TLS меня вполне устроит
     
  11. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    DevilDevil,

    Если поток крэшит, то вызывается не загрузчик в котором какие то тлс, а обратный ядерный вызов для сообщения про фаулт, затем после двух попыток обработки процесс будет прибит.

    Тупо загрузи длл и смотри dll_detach. Это сработает лишь при штатном добровольном завершении потоков.
     
  12. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Меня это устраивает
    Но если можешь посоветовать грамотный хук - я с удовольствием послушаю
    Ещё я думаю, что может быть существует какой-то отложенный ивент, типа IOCP, который будет вызван в случае поток отработает?
     
  13. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    875
    1. Ничего не нужно. Просто вызывай FlsAloc, FlsSetValue.
    2. С COM не нужно связываться.
    3. Фиберы уже давно в винде.
     
  14. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    DevilDevil,

    > IOCP, который будет вызван в случае поток отработает?

    Просто вот смотри, крэшнул тред, к примеру его стек покоцался и ядро не сможет послать нотифи в юзер - прикончит процесс; в старших версиях все структуры охраняются, если они не связаны вызывается ядро(int29) и сразу процесс прикончится. Это значит что ждущие потоки в том же процессе никогда не дождуться, а будут завершены, сразу все. Поэтому нужен как минимум второй мониторящий процесс. Древний штатный механизм - отладочные порты.
     
  15. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Зачем мне нештатная ситуация? Меня интересуют в первую очередь штатные средства. И желательно минимальными ресурсами
     
  16. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    DevilDevil,

    А чем же интересны штатные завершения тредов, даже представить не могу. Это нужно для анализа ошибок, крэши/деадлоки/утечки/статистика. А зачем нужно мониторить exitthread :my_name_is_grisha:
     
  17. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Я пишу менеджер памяти, который привязан к TLS. Нужно грамотно обрабатывать случаи, когда поток завершается
     
  18. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.455
    Адрес:
    Россия, Нижний Новгород
    Это решается, если все потоки создаются и уничтожаются твоими библиотечными функциями (как, например, в случае библиотеки pthread). Если же поток уничтожается сервисами системы напрямую, отследить его нельзя.
    И все менеджеры памяти основываются на том, что пользователь будет использовать лишь предоставляемые менеджером функции.
     
  19. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Действительно FlsAlloc/FlsSetValue хорошо работает, главное - задать значение отличное от NULL
    Но оно работает начиная с Vista, а мне хотелось бы поддерживать XP
    Может скомпилирует кто-то объектник под Win64 стандартным образом, который я попробую заюзать в Delphi?
    --- Сообщение объединено, 1 июн 2020 ---
    А разве в POSIX можно создать поток не из pthread.h?
     
  20. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.455
    Адрес:
    Россия, Нижний Новгород
    А к чему внутри сводится pthread? К системным вызовам в ядро линукса. Если не ошибаюсь, clone, который в ядре сводится к do_fork. И что помешает пользователю сделать этот сисколл?