Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.11.27;
Скачать: CL | DM;

Вниз

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

 
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 вся ветка

Текущий архив: 2005.11.27;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.045 c
14-1131330279
Petr V . Abramov
2005-11-07 05:24
2005.11.27
проблемы Франциии


2-1131531155
Al_Ba
2005-11-09 13:12
2005.11.27
Помогите ПЛЗ..........


2-1131802914
ЯТутаНовичек
2005-11-12 16:41
2005.11.27
Создание сообщения Outlook в delphi


14-1130738782
syte_ser78
2005-10-31 09:06
2005.11.27
просто интересно.


2-1131734590
vpavel
2005-11-11 21:43
2005.11.27
Графика