Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2005.11.27;
Скачать: [xml.tar.bz2];

Вниз

Синхронизация двух процессов   Найти похожие ветки 

 
DeadMeat ©   (2005-09-26 11:41) [0]

Доброго времени суток, уважаемые.
Вот такая у меня проблемка появилась.
Есть два процесса. Один процесс запускает другой. В каждом их них стоит проверка на существование друг-друга (WaitForSingleObject). В первом она стоит в основном потоке, а во втором - это отдельный поток.
Первый процесс мой - второй соответственно не мой.
Если в первом все ок, то во втором уже дурдом.
Мне нужно сделать так, чтобы при завершении одного из них, завершался и другой. Учитывая что второй процесс не моих рук дело, я решил использовать внедрение. Но до этого дело не дошло.
Для начала решил проверить в чистом проекте сам способ.
Так вот. Для проверки запускаю "блокнот" и "синхронизирую" свой процесс с ним, т.е. когда блокнот закроют мне надо закрыть себя.
Идея следующая:
- получить handle целевого процесса (за которым надо следить) используя OpenProcess;
- запустить на выполнение поток, передав ему этот handle;
- в потоке уже использовать WaitForSingleObject;
- после нее, уже ExitProcess (0).

Начал реализовывать:

.....
var thid:cardinal;
.....
function watcher (param:pointer):integer;
var bufhnd:THandle;
begin
bufhnd:=THandle (param^);

MessageBox (0,pchar (inttostr (bufhnd)),"Handle",mb_ok);
end;
.....
var bufhnd:THandle;
begin
bufhnd:=OpenProcess (SYNCHRONIZE,false,4064); //здесь PID я вручную поставил, чтобы не возиться с поиском.. знаю.. плохо.. но лень.. зато 100% он правильный.

MessageBox (0,pchar (SysErrorMessage(GetLastError)),"Result",mb_ok);

caption:=inttostr (bufhnd);
beginthread (nil,0,watcher,@bufhnd,0,thid);
end;


Правильно ли я все сделал?

Так или иначе вот в чем проблема:
- при запуске потока, значение получается совсем другое.. вообще "левое";
- при пошаговом выполнении, все прекрасно работает, т.е. значение получается нужное;
- если этот же кусок кода вставит в DLL, которая внедряется во "второй" процесс (естественно без caption.. тут это просто для отладки.. так проще...), то GetLastError уже говорит чтото типа "Параметр задан не верно", а в чистом проекте все ок;
- если в DLL, в этом куске убрать beginthread, то GetLastError уже возвращает "Операция прошла успешно".

Не могли бы Вы меня, уважаемые мастера, "ткнуть" носом туда, где я ошибся...??
Заранее благодарен за любую информацию.


 
Digitman ©   (2005-09-26 12:15) [1]

начнем с того, что процессы не могут ждать друг-друга, чтобы "одновременно завершиться" - сие есть классическая ситуация "мертвой блокировки" (deadlock)


 
GuAV ©   (2005-09-26 13:05) [2]


> - при запуске потока, значение получается совсем
> другое.. вообще "левое";


Ты наверное передаёшь указатель на локальную преременную в BeginThread. Когда дело доходит до потока, она уже не существует. Передавай:
1. Саму переменную
2. Дин. выделенную переменную, в чатности запись или класс, который освобождай из watcher.
3. Ничего не передавай, используй глобальную переменную.


 
GuAV ©   (2005-09-26 13:09) [3]


> - после нее, уже ExitProcess (0).


Плохо. IMHO, Halt(0) лучше. При этом нужно проследить, чтобы основной поток не вызвал Halt.

Наилучшим вариантом будет ожидание в основном потоке. Если там требуется обрабатывать сообщения, можно ожидать через MsgWaitчегототам.


 
ANB ©   (2005-09-26 14:01) [4]


> Есть два процесса. Один процесс запускает другой. В каждом
> их них стоит проверка на существование друг-друга (WaitForSingleObject).
>  В первом она стоит в основном потоке, а во втором - это
> отдельный поток.

1) если модуль второго процесса написан не тобой, то как ты этого добьешься ?
2) Какой у этого логический смысл ?
3) Для синхронизации в одну сторону делается все просто :
а) из своего приложения запускашь управляемый процесс (CreateProcess). Далее в этом же своем потоке ждешь, пока он не завершиться, любым способом, например :

// Найдем хэндл текущего процесса
hProcess := OpenProcess (SYNCHRONIZE, False, dwProcessID);
try
 // Если ошибка - процесс уже закончился и можно выходить.
 if (hProcess = 0) then Exit;
 tmStart := Now;
 while (TimeIntervalToMiliSec(Now - tmStart) <= tmWait) do begin
  if (fmLog.bStop) then Exit; // Это моя обработка нажатия кнопки стоп, можешь запихать всюда все, что нужно. Не забудь Application.ProcessMessages;
  dwRW := WaitForSingleObject(hProcess, 100);
  if ((dwRW = WAIT_ABANDONED) or (dwRW = WAIT_OBJECT_0)) then begin
   Exit;
  end;
 end;
finally
 CloseHandle(hProcess);
end;


4) При работе с внедренной DLL нужно учитывать, что все глобальные/локальные ее переменные в другом процессе очищаются и нужно заново их инициализировать. Чтобы передать какие то данные, их нужно передавать через MMF или сообщения.


 
DeadMeat ©   (2005-09-26 14:38) [5]


> Digitman ©   (26.09.05 12:15) [1]

Честно сказать не совсем понял, что вы имели ввиду. Мне всего то надо, закрыть одну программу, когда другую закроют. И более ничего.


> GuAV ©   (26.09.05 13:05) [2]

Вот, блин, об этом я совсем не подумал. Упустил из виду. Видимо погаговая трассировка, при которой все работает, сбила меня с толку... Спасибо.


> GuAV ©   (26.09.05 13:09) [3]

Учту.. Спасибо еще раз.


> ANB ©   (26.09.05 14:01) [4]


> 1) если модуль второго процесса написан не тобой, то как
> ты этого добьешься ?

Внедрив DLL, в которой будет проверка на "существование" первого процесса.


> 2) Какой у этого логический смысл ?

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


> 3) Для синхронизации в одну сторону делается все просто
> :
> а) из своего приложения запускашь управляемый процесс (CreateProcess).
>  Далее в этом же своем потоке ждешь, пока он не завершиться,
>  любым способом, например :

Примерно так у меня все и реализовано. С этим проблем нет, но все равно спасибо. Только еще проще: запуск через CreateProcess и ожидание через WaitForSingleObject. После этого просто выход из основного потока. Паралельно ведется своя работа в дополнительном потоке.


> 4) При работе с внедренной DLL нужно учитывать, что все
> глобальные/локальные ее переменные в другом процессе очищаются
> и нужно заново их инициализировать. Чтобы передать какие
> то данные, их нужно передавать через MMF или сообщения.

Спасибо за замечание. Нечто похожее уже реализовано и с этим тоже проблем пока не наблюдается.

Спасибо еще раз всем за ответы.
Чуть позже смогу проверить и "доложить".


 
GuAV ©   (2005-09-26 15:01) [6]


>> Digitman ©   (26.09.05 12:15) [1]
>
> Честно сказать не совсем понял, что вы имели ввиду.


Имелось ввиду, что если один поток 1 не сигнализирует объект А, пока не будет сигнализирован объект Б, а поток 2 не сигнализирует объект Б, пока не будет сигнализирован объект А, наступает взаимоная блокировка этих потоков, "тупик" или "deadlock".
К твоему случаю было бы применимо если бы таждый из процессов завершался бы тогда, и ТОЛЬКО тогда, когда завершается другой.


 
DeadMeat ©   (2005-09-26 15:25) [7]


> GuAV ©   (26.09.05 15:01) [6]


Теперь понятно. Спасибо за разьяснения.
У меня действительно случай несколько иной. Каждый из процессов может быть завершен принудительно пользователем.

По сабжу... Все работает. Перенес переменную в глобальную.
Спасибо всем, вопрос исчерпан. Далее буду допирать сам.. в чем было дело.


 
GuAV ©   (2005-09-26 15:36) [8]

Ещё замечание... чужой процесс IMHO лучше всего завершать через WM_SYSCOMMAND - SC_CLOSE его окну, чтобы он мог выполнить действия по завершению, и "убивать" через ExitProcess уже по таймауту.


 
Leonid Troyanovsky ©   (2005-09-26 16:13) [9]


> GuAV ©   (26.09.05 15:36) [8]

> действия по завершению, и "убивать" через ExitProcess уже
> по таймауту.


Тут либо TerminateProcess по таймауту (снаружи),
либо уж дать WM_SYSCOMMAND - SC_CLOSE отработать до конца
(куда уж тут совать таймаут).

--
Regards, LVT.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2005.11.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.015 c
4-1127738787
NikNet
2005-09-26 16:46
2005.11.27
Как закрасить весь PageControl?


1-1130705369
ArchValentin
2005-10-30 23:49
2005.11.27
Прозрачный TEdit


2-1131575395
solenko
2005-11-10 01:29
2005.11.27
Ошибка при вызове dll из VBA


14-1131453530
Priest
2005-11-08 15:38
2005.11.27
Подскажите интернет магазин


14-1130913575
КаПиБаРа
2005-11-02 09:39
2005.11.27
Как научиться





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский