Странное поведение CreateThread.

Тема в разделе "WASM.WIN32", создана пользователем CrawlUp, 10 дек 2018.

  1. CrawlUp

    CrawlUp Member

    Публикаций:
    0
    Регистрация:
    1 фев 2018
    Сообщения:
    90
    Создаю поток с помощью этой функции
    Код (C):
    1. HANDLE handle = 0;
    2.          
    3.             DWORD ThreadID;
    4.          
    5.             while (handle == 0)
    6.             {
    7.                 Sleep(100);
    8.                 handle = CreateThread(NULL, 10000, (LPTHREAD_START_ROUTINE)Thread_SyncDATA, (VOID*)&list_process, 0, &ThreadID);
    9.                 CloseHandle(handle);
    10.             }
    11. .......
    12. DWORD WINAPI Thread_SyncDATA(LPVOID lParametr)
    13. {
    14. бла... бла... бла...
    15. }
    Поток создается при инициализации диалового окна, но происходит это через раз, то создаётся, то нет, причин для такого поведения функции я найти не могу. Перепробывал уже все известные мне варианты записи функции для потока, не чего не помогает.
     
  2. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    А GetLastError в случае несоздания что говорит? И как проверяешь, что создался?
     
  3. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Дайте угадаю. Процедура в длл-майн. Это значит что происходит гонка потоков, происходит деадлок, поэтому и поведение апп от фазы луны зависит :lol:

    А тс не использует даже отладчик и поэтому запуск и блокировку потока не видит :)
     
    M0rg0t нравится это.
  4. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    Кстати, недавно дебажил такую фигню, даже сэмулировал исскуственно. Странная вещь, олли показывает что потоки создаются, но система их не видит (process explorer). Создаются из дллмейн, которая, в свою очередь, загружена из другой дллмейн.
     
  5. Indy_

    Indy_ Well-Known Member

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

    Да просто всё, не нужны никакие статусные коды. Он дёргает апи не читая их описание.
     
  6. CrawlUp

    CrawlUp Member

    Публикаций:
    0
    Регистрация:
    1 фев 2018
    Сообщения:
    90
    Увы я не силён в "жаргонной" терминологии, знаю main процедуру, процедуру обработки сообщений окна, и dll библиотеки. Буду предполагать, что длл-майн это процедура обработки сообщений окна. Если я всё правильно понял, значит создавать потоки при инициализации диалогового окна нельзя.
    GetLastError говорит: "Недостаточно памяти для обработки команды". Проверяю, брекпойнт срабатывает в процедуре потока, значит создался, если нет, не создался :).
     
  7. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Логика железная. Нет, "длл-маин" это dllmain https://docs.microsoft.com/en-us/windows/desktop/dlls/dllmain
    Размер стека выставь 0, чтобы дефолтный был и while(handle == 0) убери. Винда конечно кривая, но не настолько чтобы так делать. В цэ не силен, но Thread_SyncDATA я бы на &Thread_SyncDATA махнул на всякий случай. А еще проще собрать пример и выложить, а то методом Кашпировского можно очень долго разбираться в какой-нибудь ерунде.
     
  8. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Да обращал внимание, просто цэ не моё. Чем тупей, тем надежней.
     
  9. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Механизм обработки гуя довольно сложен. Там тоже есть синхронизации. В принципе значения не имеет - каким образом произошла взаимоблокировка потоков.

    Даже методом проб, можно найти суть проблемы. Прошли сутки а тс ничего не решил. Не смотря на то, что это самые простые проблемы которые могут быть.

    CrawlUp,

    > GetLastError говорит:

    Смысл той апи - прочитать из среды поле с инфой про ошибку. Но если ошибки нет, то там предыдущее значение, те не корректное. А есчо winerror - коды обьединяют в группы ntstatus. Это утеря инфы, не следует это использовать(винапи коды ошибок). Это инфа ниочём всегда, не ясно даже зачем это реализовано, в каждом случае это приводит к проблеме, заблуждению, а не решает проблему.
     
    q2e74 нравится это.
  10. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Щас довольный собой клерк пойдет на кл за очередным "прошло десять лет ..." ;) Пассажир новичек, он не обязан сразу все знать и уметь.
     
  11. Indy_

    Indy_ Well-Known Member

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

    Нет никаких особых требований, но минимальную работу человек должен сделать сам. Хотябы прочитать материал, по фукциям, которые использует.

    > клерк пойдет на кл

    Пока там не вычистят всё мне противно туда идти.
     
  12. CrawlUp

    CrawlUp Member

    Публикаций:
    0
    Регистрация:
    1 фев 2018
    Сообщения:
    90
    Не поленюсь, отвечу :). Я работаю на стройке. Двенадцати часовой рабочий день, к планшету могу подойти два раза, это в обед, полчаса и в чай 20 минут. На работу еду в автобусе 2 часа, с работы 1 час. Остаются девять часов на сон, помывку, программирование и тренировку. Хочешь спи, хочешь программируй, так что более 2-3 часов в день выделить на это время я не могу. В выходные там другое дело, минимум 12 часов, но до них надо дожить.
    Тут я с вами не могу согласится, если ошибки нет GetLastError так и говорит что ошибки нет.

    А решение я нашёл благодаря вашему совету, просто перенёс создание потока в Main процедуру, добавив в нём лишнюю задержку Sleep.

    Просто очень странно что в варианте ниже поток не создаётся, но если перед его созданием поставить Sleep задержку то создасться.

    Код (C):
    1. int CALLBACK WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR str_CmdLine, int nCmdShow)
    2. {
    3. DialogBoxParam(hInst, MAKEINTRESOURCE(ID_DIALOG1), 0, (DLGPROC)WndProc, 0);
    4. return true;
    5. }
    6. .....
    7. /* Обрабатывает сообщения в главном окне :: procesing message in the main window*/
    8. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    9. {
    10. switch (message)
    11. {
    12. case WM_INITDIALOG:
    13. {
    14. _hStatusBar = CreateStatusWindow(WS_VISIBLE + WS_CHILD, 0, hWnd, ID_STATUS);
    15. _hListView = CreateWindowExW(0, L"SysListView32", 0, WS_VISIBLE | LVS_REPORT | WS_CHILD |
    16. WS_BORDER | LVS_EDITLABELS | WS_EX_CLIENTEDGE, 0, 0, 0, 0, hWnd, (HMENU)ID_LISTVIEW, _hInst, 0);
    17. SendMessage(_hListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_ONECLICKACTIVATE);
    18. ShowWindow(hWnd, SW_MAXIMIZE);
    19. //инициализация объекта хранения и обработки данных
    20. list_process.Init(*list_process.Get_PointerTABLE_INFO(),_hListView, process_table);
    21. list_process.DrawTable();
    22. handle = CreateThread(NULL, 10000, (LPTHREAD_START_ROUTINE)Thread_SyncDATA, (VOID*)&list_process, 0, &ThreadID);
    23. if (handle == 0)
    24. {
    25. ErrorMessage();
    26. }
    27. CloseHandle(handle);
    28. .....
    29. case WM_CLOSE:
    30.        EndDialog(hWnd,0);
    31. break;
    32. }
    33. break;
    34. }
    Не в этом дело, я уже пробовал всякие варианты, в том числе и тот где все нули кроме имени процедуры.
     
  13. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Слип это принудительное переключение на другие потоки, видимо гонка потоков и происходила.
    --- Сообщение объединено, 12 дек 2018 ---
    Пока всё за 10 лет не вычистят?
     
  14. Indy_

    Indy_ Well-Known Member

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

    > Тут я с вами не могу согласится, если ошибки нет GetLastError так и говорит что ошибки нет.

    Нет, она возвращает предыдущую. На сколько помню трансляция статус в еррор происходит только в случае ошибки. Тогда апдейтится это поле в пеб. Но как бы там небыло не используйте winerror никогда. Иначе у вас всегда и будут не решаемые проблемы.

    > если перед его созданием поставить Sleep задержку то создасться.

    Такое быть не может. Поток запускается сразу, он не в гуе(оконной системе) запускается, а в нэйтивном окружении. Это его теневая работа, он сообщает загрузчику о своём создании и затем через перезагрузку контекста покидает загрузчик переходя на вашу заданную процедуру. Вот в ней он и блокируется. Почему предсказать невозможно - у вас в коде асинхронный огород", такой же видимо и в стартап процедуре проблемного потока. У вас рекурсивные вызовы гуя, посылки сообщений и свои синхронизации.. блокировка может быть где угодно. Если задержка снимает проблему, то это и есть та самая ошибка в синхронизации.
    --- Сообщение объединено, 12 дек 2018 ---
    CrawlUp,

    Посмотри сам, это пример из врк, для новой ос соответствия на порядок больше.

    Код (Text):
    1.     STATUS_THREAD_IS_TERMINATING, ERROR_ACCESS_DENIED,
    2.     STATUS_PROCESS_IS_TERMINATING, ERROR_ACCESS_DENIED,
    3.     STATUS_INVALID_LOCK_SEQUENCE, ERROR_ACCESS_DENIED,
    4.     STATUS_INVALID_VIEW_SIZE, ERROR_ACCESS_DENIED,
    5.     STATUS_ALREADY_COMMITTED, ERROR_ACCESS_DENIED,
    6.     STATUS_ACCESS_DENIED, ERROR_ACCESS_DENIED,
    7.     STATUS_FILE_IS_A_DIRECTORY, ERROR_ACCESS_DENIED,
    8.     STATUS_CANNOT_DELETE, ERROR_ACCESS_DENIED,
    9.     STATUS_INVALID_COMPUTER_NAME, ERROR_INVALID_COMPUTERNAME,
    10.     STATUS_FILE_DELETED, ERROR_ACCESS_DENIED,
    11.     STATUS_FILE_RENAMED, ERROR_ACCESS_DENIED,
    12.     STATUS_DELETE_PENDING, ERROR_ACCESS_DENIED,
    13.     STATUS_PORT_CONNECTION_REFUSED, ERROR_ACCESS_DENIED,
    Слева совершенно не связанные статусные(ядерные) коды, которые приводятся к одному дос значению ошибки(winerror, то что возвращает GetLastError()). При этой трансляции происходит утеря инфы и по дос коду ошибки суть не понять. Почему дос" - потому что это понятие разраба, так он в врк сурке написал:

    --- Сообщение объединено, 12 дек 2018 ---
    > апдейтится это поле в пеб.

    в теб разумеется, опечатка. Ввели лимит на редактирование постов, это хорошо! :good3:
     
    Последнее редактирование: 12 дек 2018
  15. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    обычно, если ошибка есть, то функция вернула ошибочное состояние (нулл или инвалих_хендл_валуе), то функция поставила код ошибки... если функция этого не сделала, то это баг в коде мелкомягких... и последний еррор и последний нт статус хранятся в TEB, можно и тот и другой получить... если есть какая-то параноя с этим связанная, то всегда можно руками вызвать SetLastError(0) до вызова функции...
     
  16. Indy_

    Indy_ Well-Known Member

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

    Статус в теб грузится ядром при обработке исключений вроде бы как, впрочем не важно. Как и говорил следует забыть про getlasterr.
     
  17. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    ну если ты не глупенький нт-дрочер, то кодишь на более удобном и простом вин-апи, то без гетластеррор тебе не обойтись... не говоря уже о всяких криптоапи и тд...
     
  18. Indy_

    Indy_ Well-Known Member

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

    Никогда понимающий как это работает человек такое не посоветует. Ты спалил сам себя, что впрочем не удивительно даже.
     
  19. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    как же Инде предполагает обрабатывать ошибки высокоуровневых апи? если Инде предлагает использовать нт-апи для всего, то я предлагаю Инде показать как он будет скажем искать хендл окна по его заголовку, или скажем шифровать данные алгоритмом RSA...
     
  20. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Да обычно этот GetLastError для обработки ошибок не нужен, я например его не использую. Вернула функция не тот статус - сообщаешь об этом и завершаешь функцию вернув своей фукнцией ошибку. А выяснение что там и почему уже вопрос других методов вплоть до тимвивера. Хотя именно при разработке GetLastError бывает полезен, особенно с ком-интерфейсами.