Показаны сообщения с ярлыком потоки. Показать все сообщения
Показаны сообщения с ярлыком потоки. Показать все сообщения

суббота, 23 мая 2020 г.

Отладка зависания: все потоки встали на WinHttpGetProxyForUrl

Это перевод Diagnosing a hang: Everybody stuck in WinHttpGetProxyForUrl. Автор: Реймонд Чен.

Клиент сообщил, что их программа рано или поздно полностью встаёт, а все её потоки (750 штук) зависают при вызове WinHttpGetProxyForUrl со следующим стеком вызова:
ntdll!ZwWaitForSingleObject+0x14
KERNELBASE!WaitForSingleObjectEx+0x8f
winhttp!OutProcGetProxyForUrl+0x160
winhttp!WinHttpGetProxyForUrl+0x349
contoso!submit_web_request+0x232
ntdll!TppWorkpExecuteCallback+0x35e
ntdll!TppWorkerThread+0x474
kernel32!BaseThreadInitThunk+0x14
ntdll!RtlUserThreadStart+0x21
(я упростил стек вызова для простоты объяснения)

четверг, 5 сентября 2019 г.

Обновлено: Если FlushInstructionCache ничего не делает, почему я должен её вызывать?

Это перевод If FlushInstructionCache doesn’t do anything, why do you have to call it, revisited. Автор: Реймонд Чен.

Предполагается, что вы будете вызывать функцию FlushInstructionCache, когда вы генерируете или модифицируете исполняемый код в run-time - чтобы процессор при выполнении вашего сгенерированного/модифицированного кода читал бы написанные вами инструкции, а не старые инструкции, которые могут остаться в кеше команд процессора.

Ранее мы узнали, что в Windows 95 функция FlushInstructionCache не делает ничего, кроме возврата. Это потому, что простого вызова функции было достаточно, чтобы очистить кэш команд.

Но в Windows NT функция FlushInstructionCache выполняет реальную работу, поскольку ей необходимо уведомить все остальные процессоры о необходимости очищать их кэши.

Однако если вы посмотрите на Windows 10, то вы обнаружите, что функция FlushInstructionCache выглядит как версия для Windows 95: она ничего не делает.

В чём тут дело?

среда, 19 декабря 2018 г.

вторник, 13 января 2015 г.

Интерфейс пользователя + многопоточный апартмент = смерть

Это перевод User interface code + multi-threaded apartment = death. Автор: Реймонд Чен.

Существуют однопоточные апартменты (single-threaded apartment) и многопоточные апартменты (multi-threaded apartment). Ну, сначала существовали только однопоточные... Нет, давайте начнём по-другому.

понедельник, 10 сентября 2012 г.

Что означает исключение Invalid Handle в LeaveCriticalSection?

Это перевод What does an invalid handle exception in LeaveCriticalSection mean? Автор: Реймонд Чен.

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

Как безопасно отправить SIGINT в главный поток?

Это перевод How can SIGINT be safely delivered on the main thread? Автор: Реймонд Чен.

Комментатор AnotherMatt интересуется, почему консольные программы Win32 получают уведомления в фоновом потоке. Почему бы не отправлять их в главный поток?

пятница, 26 августа 2011 г.

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

Это перевод Before you can learn to recognize what's wrong, you must learn to recognize what's right. Автор: Реймонд Чен.

Иногда, когда я отлаживаю проблему, я могу проигнорировать какой-то поток, а кто-то спросит: "а что делает этот поток? Почему ты его игнорируешь?"

Мой ответ: "Я понятия не имею, что он делает, но что бы он ни делал, это - нормально".

среда, 29 июня 2011 г.

Тревожное ожидание - это не-GUI аналог для GUI-шной прокачки сообщений

Это перевод The alertable wait is the non-GUI analog to pumping messages. Автор: Реймонд Чен.

Когда вы программируете GUI приложения, вы хорошо знаете, что прокачка сообщений (message pumping) является основным способом по приёму и диспетчеризации сообщений. Невизуальным аналогом прокачки сообщений является ожидание в тревожном состоянии (alertable wait).

воскресенье, 29 мая 2011 г.

Основные негласные правила программирования: параметры функций

Это перевод Basic ground rules for programming - function parameters and how they are used. Автор: Реймонд Чен.

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

среда, 9 февраля 2011 г.

Привязка к потокам объектов пользовательского интерфейса, часть 5: очистка объектов

Это перевод Thread affinity of user interface objects, part 5: Object clean-up. Автор: Реймонд Чен.

Оконный менеджер и GDI, как правилo, уничтожают все объекты, созданные процессом, когда этот процесс завершается (оконный менеджер также уничтожает окна, когда завершается их поток-владелец). Заметьте, что это - только ремни безопасности. Это не оправдание для вашей программы не освобождать ресурсы. "А, да пофиг, всё равно система за мной подчистит". Поскольку это ремни безопасности, то они не должны быть вашей основной мерой защиты.

вторник, 8 февраля 2011 г.

Привязка к потокам объектов пользовательского интерфейса, часть 4: объекты GDI и другие замечания

Это перевод Thread affinity of user interface objects, part 4: GDI objects and other notes on affinity. Автор: Реймонд Чен.

GDI объекты более просты. Обычное правило: все они имеют привязку к потоку: все они могут быть использованы любым потоком, но только в том процессе, который их создал. Если вы используете GDI-объекты из нескольких потоков, то координировать их использование - ваша ответственность.

понедельник, 7 февраля 2011 г.

пятница, 4 февраля 2011 г.

Привязка к потокам объектов пользовательского интерфейса, часть 1: оконные описатели

Это перевод Thread affinity of user interface objects, part 1: Window handles. Автор: Реймонд Чен.

У разных объектов есть разные правила привязки к потокам - но базовые принципы пришли ещё из времён 16-ти битных Windows.

четверг, 20 января 2011 г.

Понимание последствий WAIT_ABANDONED

Это перевод Understanding the consequences of WAIT_ABANDONED. Автор: Реймонд Чен.

Одним важным отличием мьютексов от всех остальных объектов синхронизации является то, что мьютексы имеют владельца. Если поток, который владеет мьютексом, завершается без освобождения мьютекса, то мьютекс автоматически освобождается.

Но если это произошло - то у вас большие проблемы.

среда, 15 декабря 2010 г.

Ничто не пахнет хуже локали потока, чем кодовая страница потока

Это перевод Nothing stinks worse than the thread locale, other than the thread code page. Автор: Майкл Каплан.

Вот кусок из письма, которое я получил от Ken:
Привет, Майкл.

Я встретился с чем-то, что, как я считаю, является багом в MultibyteToWideChar и WideCharToMultibyte, когда параметр кодовой страницы устанавливается в CP_THREAD_ACP, 'язык по-умолчанию для не-Unicode приложений' - установленный в иврит. Это видно, когда используется вспомогательный макрос из atlconv.h вроде T2WC.

Я создал простое тестовое приложение, которое показывает неожиданные результаты на некоторых системах. Кодовая страница от CP_THREAD_ACP получается не той же самой, что GetACP. Я воспроизвёл это на двух системах с ивритом, но не на системах, где стоит традиционный китайский - одна из которым имеет полностью локализированный в традиционном китайском UI. Исходник является частью консольного проекта .NET 2003 по умолчанию.
#include "stdafx.h"
#include <ostream>
int _tmain(int argc, _TCHAR* argv[])
{
    std::cout << "default code page is " << GetACP() << std::endl;
    std::cout << "_AtlGetConversionACP code page is " << ATL::_AtlGetConversionACP() << std::endl;

    CPINFOEX cpinfo = {};
    GetCPInfoEx(ATL::_AtlGetConversionACP(), 0, &cpinfo);

    std::cout << "Thread code page is " << cpinfo.CodePage << std::endl;
    return 0;
}
Мои результаты:
default code page is 1255
_AtlGetConversionACP code page is 3
Thread code page is 1252
Когда моё приложение вызывает T2WC, оно получает неверный результаты, а кодовые точки расширяются до 16-ти бит, но не конвертируются в кодовые точки иврита. Мы обходим это использованием _CONVERSION_DONT_USE_THREAD_LOCALE, но мне любопытно, сталкивался ли кто-то ещё с этой проблемой ранее.

Спасибо за потраченное на меня время,
Ken
Постоянные читатели могут вспомнить, почему я не люблю локаль потока.

(Фактически, меня не так давно попросили помочь вычистить несколько плохих случаев использования локали потока в различных частях Windows в shell32.dll и shlwapi.dll - наверное, скоро я за это засяду!)

вторник, 14 декабря 2010 г.

Почему я считаю, что локаль потока действительно воняет

Это перевод Why I think the thread locale really stinks. Автор: Майкл Каплан.

Я не люблю локаль потока (thread locale).

Да, GetThreadLocale и SetThreadLocale являются двумя из многих NLS функций, которыми владеет команда GIFT.

И да, если вы посмотрите на функции, которыми мы владеем, как если бы они были нашими детьми, то нам следовало бы любить их всех.

В таком случае я думаю, что из меня никудышный родитель (если вы помните, я также считаю, что SetLocaleInfo - тоже отстой).

вторник, 9 ноября 2010 г.

Опрос засыпанием против опроса ожиданием с таймаутом

Это перевод Polling by sleeping versus polling by waiting with a timeout. Автор: Реймонд Чен.

Комментатор Francois Boucher спросил, в фоновом потоке лучше ли делать опрос со Sleep и флагом или опрос с ожиданием на событии?
// Метод A
while fKeepGoing do
begin
  ... немного работы ...
  Sleep(50);
end;

// Метод B
repeat
  ... немного работы ...
until (WaitForSingleObject(hEvent, 50) <> WAIT_TIMEOUT);
Какой сценарий лучше? Первый использует только один описатель - для потока. Второй использует два. Тратит ли первый пример больше потокового времени? Стоит ли использовать ещё и событие (объект ядра)?"

понедельник, 8 ноября 2010 г.

Следствия из алгоритма планировщика: засыпание помогает не всегда

Это перевод Consequences of the scheduling algorithm: Sleeping doesn't always help. Автор: Реймонд Чен.

Чаще всего я вижу проблемы, обратные к теме "поток с низким приоритетом может работать даже когда в системе есть активный поток с высоким приоритетом". А именно: люди, которые думают, что Sleep(0) является чистым способом отдать процессор (yield). Например, у них могли закончиться вещи, которые можно делать, и они просто хотят, чтобы другой поток делал работу.

Вспомните, что планировщик потоков ищет готовый выполняться поток с самым высоким приоритетом - а если их несколько, то все они равноправны. Поток может вызвать Sleep(0), чтобы отдать остаток своего кванта времени раньше срока, уменьшая, таким образом, свою долю в работе процессора. Заметьте, однако, что это не гарантирует, что запустится другой поток.

воскресенье, 7 ноября 2010 г.