Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > завершение родительского процесса из дочернего


Автор: ihtiandr 15.7.2011, 15:41
Всем доброго времени суток.
Мне нужно из дочернего процесса закрыть родительский, но ничего не выходит.
Вот исходник дочернего
Код

#include<windows.h>
#include<conio.h>

int main(int argc, char *argv[])
{
char c;
HANDLE hThread;

hThread =  (HANDLE)atoi(argv[1]);

while (true)
  {
   cputs("Input 't' to terminate the thread: ");
   c =_getch();
   if (c=='t')
     {
      cputs("t\n");
      break;
     }
    TerminateThread(hThread,0);
    CloseHandle(hThread);
    cputs("Pres any key to exit.\n");
    _getch();
    return 0;
  }
}


Вот родительского
Код


#include<windows.h>
#include<conio.h>
volatile int count;

void thread()
{
for(;;)
{
count++;
Sleep(500);
cprintf("count= %d\n",count);
}
}

int main()
{
char lpszComLine[80];
STARTUPINFO si;
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sa;

HANDLE hThread;
DWORD IDThread;

sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = True;

hThread = CreateThread(&sa,0,(LPTHREAD_START_ROUTINE)thread, NULL, 0, &IDThread);

if(hThread == NULL)
return GetLastError();

ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);

wsprintf(lpszComLine,"c:\\CP.exe %d",(int)hThread);

if(!CreateProcess(
NULL,
lpszComLine,
NULL,NULL,
TRUE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi))
{
cputs("The new process is't created");
_getch();
return GetLastError();
}

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

WaitForSingleObject(hThread,INFINITE);
        cputs("Press any key to exit");
        _getch();
CloseHandle(hThread);
return 0;


}



Когда запускаю родительский процесс он запускает дочерний а в дочернем при нажатии на "t" сам себя закрывает а родительский продолжает работать.
Помогите разобраться. 

Автор: YDean 15.7.2011, 18:51
Значение, возвращаемое функцией CreateThread, валидно только в контексте вызывающего ее процесса.
Для передачи описателей(handles) между процессами нужно использовать DuplicateHandle.

В данном примере нужно передать описатель потока, а также реальный описатель процесса. 
Чтоб в том процессе по ним восстановили правильный описатель потока.

Поскольку GetCurrentProcess() возвращает псевдоописатель текущего процесса, перед отправкой его нужно преобразовать в реальный через
DuplicateHandle(GetCurrentProcess(),GetCurrentProcess(),GetCurrentProcess(), &hRealProcess, 0,0 1,DUPLICATE_SAME_ACCESS)


Хотя, TerminateThread использовать нехорошо. Он не освобождает стек потока.
(еще могут быть проблемы с правами на разных виндах)
Лучше передавать mutex. 
Или не передавать, а создавать и открывать именованный mutex/event.

Автор: ihtiandr 16.7.2011, 06:49
YDean
Я изменил родительский процесс используя DuplicateHandle
Вот код:

Код

#include<windows.h>
#include<conio.h>
volatile int count;

void thread()
{
for(;;)
{
count++;
Sleep(500);
cprintf("count= %d\n",count);
}
}

int main()
{
char lpszComLine[80];
char lpszHandle[20];
STARTUPINFO si;
PROCESS_INFORMATION pi;

HANDLE hThread, hInheritThread;
DWORD IDThread;



hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)thread, NULL, 0, &IDThread);
wsprintf(lpszComLine,"c:\\CP.exe %d",(int)hThread);

if(!DuplicateHandle(GetCurrentProcess(),
hThread,
GetCurrentProcess(),&hInheritThread,
 0,TRUE,DUPLICATE_SAME_ACCESS))

ZeroMemory(&si,sizeof(STARTUPINFO));
 si.cb = sizeof(STARTUPINFO);
 itoa((int)hInheritThread,lpszHandle,10);
 strcat(lpszComLine,lpszHandle);

if(!CreateProcess(
NULL,
lpszComLine,
NULL,NULL,
TRUE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi))

{
cputs("The new process is't created");
_getch();
return GetLastError();
}

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
_getch();

CloseHandle(hThread);
return 0;

}


Теперь у меня при запуске родительского процесса дочернимй вообще не выходит а монитор становится красным и выходит ошибка"Ошибка при инициализации приложения 0хс0000005" при нажатии на "Ок" родительский процесс не завершается а продолжается.

Автор: ASMatic 16.7.2011, 12:42
ihtiandr, правильней не убивать процесс,а оповещать его что пора ему завершится.
Уже подсказывали как
http://msdn.microsoft.com/en-us/library/ms682396(v=VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms686211(v=VS.85).aspx
создаем, указываем нейм. Открываем.
WaitForSingleObject(), можно заюзать с таймаутом и время от времени в треде проверять.

*а с кодом что вашим - почему бы под отладчиком не посмотреть на какой инструкции получаем #AV

Автор: YDean 16.7.2011, 19:54
ihtiandr, опять неверно
DuplicateHandle  преобразует описатели между процессами.
Поскольку при формировании строки запуска дочерний процесс еще не существует - то и преобразовать к нему мы не сможем. 
Это он должен сделать сам.
Для этого ему нужен реальный описатель родительского процесса.


И ASMatic дело говорит. 
Я именно это и пытался сказать выше после "Хотя...".

Автор: bass 16.7.2011, 20:15
Ребят дубликате хандле конечно круто, но задача вообще банальна..........

Если приложение (родитель)GDI....... то передаем дескриптор главного окна HWND ....... Процес (ребенок) постмессаге вм_клосе.....
Приношу извинения за написание на русском языке..........................

Консольное приложение процесс родитель передает дочерниму  IdProcees GetCurrentProcessId .............     Дочерний процесс OpenProcess Terminate.........

Корректно процесс родитель запускает процесс дочерний и остается ждать евента ...... Пришел евент exit(0);

Автор: Estranged 16.7.2011, 23:51
YDean, DuplicateHandle в таком виде не подойдет. А HANDLE он может передать, потому что sa.bInheritHandle = TRUE;. Дочерний процесс может использовать его.

Ошибка не давала этому чуду работать:
Код

while (true)
  {
   cputs("Input 't' to terminate the thread: ");
   c =_getch();
   if (c=='t')
     {
      cputs("t\n");
      break; <---------------- TerminateThread(hThread,0); не выполнялся просто
     }


Добавлено через 5 минут и 58 секунд
И еще у родительского заменить void thread() на DWORD WINAPI thread(LPVOID)

Автор: YDean 17.7.2011, 11:15
Смешно.  smile 
Estranged, +1
Цитата
DuplicateHandle в таком виде не подойдет.
Всю жизнь работало. 
Jeffrey Richter ошибается? smile
Цитата
А HANDLE он может передать, потому что sa.bInheritHandle = TRUE;. Дочерний процесс может использовать его.
Это правда. Недосмотрел.

Автор: Estranged 17.7.2011, 12:35
YDean, DuplicateHandle(GetCurrentProcess(),GetCurrentProcess(),GetCurrentProcess(), &hRealProcess, 0,0,DUPLICATE_SAME_ACCESS)

Да Рихтер прав, в http://msdn.microsoft.com/en-us/library/ms724251%28v=vs.85%29.aspx написано все, о чем http://wm-help.net/books-online/book/59464/59464-22.html#head3top3p3 не сказал явно, только намекал.

Внимание, вопрос: для какого процесса приведенный пример создает дубликат HANDLE текущего процесса?

Автор: YDean 18.7.2011, 22:51
Да, да, да. Всё понятно.  smile 
bInheritHandle=1

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)