Vienna

Chapter 8) 프로세스 간 통신(IPC) 2 - 핸들 정보의 상속 본문

그외/뇌를 자극하는 윈도우즈 시스템 프로그래밍

Chapter 8) 프로세스 간 통신(IPC) 2 - 핸들 정보의 상속

아는개발자 2023. 4. 26. 12:27

◇ 예제를 통해서 확인하는 핸들 정보의 상속

#define _CRT_SECURE_NO_WARNINGS

/*
* MailSender2_1.cpp
*
* 프로그램 설명: 핸들의 상속 확인용 예제. 부모 프로세스
*/

#include <stdio.h>
#include <tchar.h>
#include <windows.h>

#define SLOT_NAME _T("\\\\.\\mailslot\\mailbox")

int _tmain(int argc, TCHAR* argv[])
{
	HANDLE hMailSlot;
	TCHAR message[50];
	DWORD bytesWritten;

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

	hMailSlot = CreateFile(
		SLOT_NAME,
		GENERIC_WRITE, FILE_SHARE_READ,
		&sa, OPEN_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (hMailSlot == INVALID_HANDLE_VALUE) {
		_fputts(_T("Unable to create mailslot\n"), stdout);
		_tprintf(_T("Error code: %d\n"), GetLastError());
		return 1;
	}

	_tprintf(_T("Parent Process\n"), stdout);
	_tprintf(_T("Inheritable Handle: %d \n"), hMailSlot);
	FILE* file = _tfopen(_T("InheritableHandle.txt"), _T("wt"));
	_ftprintf(file, _T("%d"), hMailSlot);
	fclose(file);

	STARTUPINFO si = {0, };
	si.cb = sizeof(si);
	PROCESS_INFORMATION pi;
	TCHAR command[] = _T("MailSender2_2.exe");

	CreateProcess(NULL, command, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);

	while (1) {
		_fputts(_T("MY CMD>"), stdout);
		_fgetts(message, sizeof(message) / sizeof(TCHAR), stdin);

		if (!WriteFile(hMailSlot, message, _tcslen(message) * sizeof(TCHAR), &bytesWritten, NULL)) {
			_fputts(_T("Unable to write!"), stdout);
			CloseHandle(hMailSlot);
			return 1;
		}

		if (!_tcsncmp(message, _T("exit"), 4)) {
			_fputts(_T("Good bye!"), stdout);
			break;
		}
	}

	CloseHandle(hMailSlot);

	return 0;
}
#define _CRT_SECURE_NO_WARNINGS

/*
* MailSender2_2.cpp
*
* 프로그램 설명: 핸들의 상속 확인용 예제. 자식 프로세스
*/

#include <stdio.h>
#include <tchar.h>
#include <windows.h>

#define SLOT_NAME _T("\\\\.\\mailslot\\mailbox")

int _tmain(int argc, TCHAR* argv[])
{
	HANDLE hMailSlot;
	TCHAR message[100];
	DWORD bytesWritten;

	/****************** 핸들을 얻는 코드******************/
	
	FILE* file = _tfopen(_T("InheritableHandle.txt"), _T("rt"));
	_ftscanf_s(file, _T("%d"), &hMailSlot);
	fclose(file);
	_tprintf(_T("Child Process\n"), stdout);
	_tprintf(_T("Inheritable Handle: %d \n"), hMailSlot);
	
	/***************************************************/

	while (1) {
		_fputts(_T("MY CMD>"), stdout);
		_fgetts(message, sizeof(message) / sizeof(TCHAR), stdin);

		if (!WriteFile(hMailSlot, message, _tcslen(message) * sizeof(TCHAR), &bytesWritten, NULL)) {
			_fputts(_T("Unable to write!"), stdout);
			_tprintf(_T("Error code: %d \n"), GetLastError());
			_gettchar();
			CloseHandle(hMailSlot);
			return 1;
		}

		if (!_tcsncmp(message, _T("exit"), 4)) {
			_fputts(_T("Good bye!"), stdout);
			break;
		}
	}

	CloseHandle(hMailSlot);

	return 0;
}

실행 결과

요 며칠 간 올리지 않은 것은, 위 예제를 따라함에도 계속해서 실패한 결과를 얻었기 때문이다.
3일 동안 시도했으나 안 된 것을 보아 이 이상 하는 것은 시간 낭비로 보인다.

메일 슬롯 핸들은 정상적으로 받아온 것으로 보이는데 왜 자식 프로세스 쪽에서 WriteFile 함수를 호출했을 때 실패했는지 이해가 되지 않는다.

그래서 책에서 읽은 대로, GetLastError() 함수를 통해 에러 코드를 받아보았다.
그 결과 6번을 받았고 6번은 다음과 같다.
유효하지 않은 핸들이라고 나온다.
하지만 자식프로세스나 부모 프로세스 그 어떤 곳에서도 while문 내부에서 CloseHandle 함수를 그냥 호출해주는 곳은 없다.
때문에 이상하고 이해가 되지 않지만, 우선 넘기기로 했다.
Comments