понедельник, 26 июля 2010 г.

Отладка телепатией: понимание инициализации DDE

Это перевод Psychic debugging: Understanding DDE initiation. Автор: Реймонд Чен.

Вы тоже можете использовать свои телепатические способности, чтобы найти решение этой проблемы:
У нас есть проблема с открытием документов в нашем приложении по двойному щелчку в Проводнике. При этом мы видим странную вещь: если мы подключим отладчик к Проводнику и установим точку останова на kernel32!CreateProcessW, то, подождав чуток после завершения CreateProcess, и нажимая возобновление процесса - тогда документ открывается нормально. Но если мы не будем ждать, то документ не открывается. Вместо этого появляется сообщение об ошибке "Windows не может найти файл 'abc.lit'. Убедитесь, что вы набрали его имя правильно и попробуйте ещё раз". Вот команда, которую мы использовали, когда встретились с этой проблемой:
"F:\Program Files\LitSoft\LitWare\LitWare.exe" /dde
Что не так?
Если вы внимательно читали объяснение как работает открытие документов через DDE, то вы уже знаете, в чём проблема.

Вспомните, что запуск документов через DDE выполняется сначала поиском DDE сервера, а затем, если таковой не найден, его запуском и повтором попытки. Командная строка выше очевидно регистрируется как команда, связанная с ddeexec. Почему? Для этого есть две подсказки. Во-первых: обратите внимание, что имя файла не участвует в командной строке (как программа узнает, какой файл ей надо открыть?). Вторая подсказка: наличие ключа /dde в командной строке.

Очевидно, что-то пошло не так, когда Проводник попытался выполнить повторную инициализацию DDE при открытии документа. Тот факт, что вставка ожидания в Проводник исправляет проблему, делает причину очевидной: DDE сервер слишком медленно инициализирует себя и не готов к коммуникации. Проводник запускает сервер и пытается с ним взаимодействовать, но сервер ещё не готов и не отвечает на инициализацию DDE.

Но как это исправить?

Оболочка предполагает, что DDE сервер готов к общению, когда он переходит к простою (input idle). Как только функция WaitForInputIdle возвращает управление, Проводник делает вторую попытку подключения. Исправление для приложения заключается в том, чтобы поднять работоспособный DDE сервер до начала цикла прокачки сообщений. Моё предположение было в том, что приложение переместило инициализацию DDE в фоновый поток, чтобы улучшить производительность запуска, поскольку DDE сервер не используется при обычной работе программы. Жаль, что программа забыла, что сервер должен работать к моменту обработки сообщений, когда ей передают флаг /dde.

Мораль истории: если вы хотите работать как DDE сервер, то убедитесь, что именно это вы и сделали, прежде чем ваш первичный поток начнёт обработку сообщений. В противном случае у вас будет условие гонки между запуском вашего приложения и оболочкой, которая пытается с вами общаться.

2 комментария:

  1. Анонимный28 июля 2010 г., 16:15

    В Википедии термин "Race condition" переводят как "Состояние гонки", я тоже склоняюсь к тому, что так лучше.

    ОтветитьУдалить
  2. Переводят и так и сяк. Лично мне больше нравится вариант с "условие", но спасибо за замечание.

    ОтветитьУдалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.