В этой проблеме есть как минимум три части, так что потерпите меня:
1) CreateProcess имеет параметр bInheritHandles, который заставляет дочерний процесс наследовать все наследуемые дескрипторы в родительском процессе. Для этого параметра должно быть задано значение TRUE, чтобы родительский элемент мог указывать дескрипторы stdin, stdout и stderr для дочернего элемента в параметре STARTUPINFO.
2) В Win32 удаление и переименование файлов может завершиться ошибкой, если для одного и того же файла открыто более одного дескриптора.
3) Функция open () Microsoft CRT по умолчанию создает наследуемые дескрипторы. Кроме того, описатели файлов, созданные по умолчанию, страдают от проблемы 2 выше.
Эта волшебная комбинация создает следующую операционную проблему: Библиотека A вызывает open () и не ожидает последующих переименований и удалений. В другом месте процесса другая библиотека B вызывает CreateProcess с bInheritHandles, установленным в TRUE (для захвата stdin / out / err), временно создавая дубликаты дескрипторов. Теперь время от времени файловые операции библиотеки A не выполняются. Естественно, библиотеки A и B содержатся отдельными людьми. Я также знаю о другой библиотеке A ', которая использует open () и страдает от аналогичной проблемы.
В этой статье kb обсуждается связанная проблема и решение. Однако он все еще основывается на вызове CreateProcess с bInheritHandles, для которого в родительском процессе установлено значение TRUE, поэтому эта проблема не решается.
Мне интересно, сталкивались ли другие с этой проблемой и нет ли известного решения?
В статье kb, приведенной выше, по существу подразумевается, что вызов CreateProcess с bInheritHandles, установленным в значение ИСТИНА, является грубым, поэтому я склонен исправить библиотеку B так, чтобы она никогда этого не делала. Я бы сделал это:
- Создать приостановленный промежуточный процесс (в идеале, используя rundll для запуска пользовательской точки входа в библиотеке B) с bInheritHandles, установленным в FALSE.
- Создайте трубы stdin / out / err и добавьте правильные концы к промежуточному процессу.
- Передайте дублированные дескрипторы промежуточному процессу.
- Возобновите промежуточный процесс.
- Из промежуточного процесса заполните STARTUPINFO трубами от родителя и вызовите CreateProcess с bInheritHandles, установленным в TRUE.
Это хорошая стратегия или есть какое-то лучшее решение?
Как бы вы порекомендовали передать дублированные маркеры промежуточному процессу на шаге 3?
Является ли пользовательская точка входа rundll + надежным способом настройки промежуточного процесса на шаге 1?