gpt4 book ai didi

c - 开放管道上 CloseHandle 上的 sigsegv

转载 作者:行者123 更新时间:2023-11-30 15:17:40 26 4
gpt4 key购买 nike

我在 CloseHandle(pipe_settings->hPipe) 上收到一个 sigsegv;我在这个例子中也使用了线程,我认为这与任何事情都没有关系,因为管道是在同一个线程中打开和关闭的。

管道句柄似乎也有效。类似于:0xcc。事件句柄也正确关闭。

这是一个完全有效的示例,您应该能够将其放入 CLion 中并开始使用。此代码在任何 Windows 安装上都应该是安全的。

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

#define UNICODE

#define PIPE_BUFFER_SIZE 4096
#define PIPE_TIMEOUT 10000
#define PIPE_MAX_CONNECT_TIMEOUT 10000
#define PIPE_CONNECT_FAIL_REPEAT_DELAY 1000
#define DUST_TEST_PIPE_NAME "\\\\.\\pipe\\DustTestPipe"
#define PIPE_TEST_TIMEOUT 100000

struct pipe_settings {
HANDLE hPipe;
OVERLAPPED ol;
LPCTSTR name;
DWORD pipe_timeout;
};

WINBOOL PipeClose(struct pipe_settings *pipe_settings)
{
//Dies on CloseHandle(pipe_settings->hPipe) but not on CloseHandle(pipe_settings->ol.hEvent)
return (CloseHandle(pipe_settings->ol.hEvent) && CloseHandle(pipe_settings->hPipe));
}

void InitializePipeSettings(struct pipe_settings *pipe_settings)
{
pipe_settings->hPipe = INVALID_HANDLE_VALUE;
pipe_settings->ol.hEvent = INVALID_HANDLE_VALUE;
pipe_settings->ol.Internal = 0;
pipe_settings->ol.InternalHigh = 0;
pipe_settings->ol.Offset = 0;
pipe_settings->ol.OffsetHigh = 0;
pipe_settings->ol.Pointer = NULL;
}

DWORD PipeConnectToClient(struct pipe_settings *pipe_settings)
{
HANDLE h;
DWORD err;

InitializePipeSettings(pipe_settings);

for(int x = 0; x < PIPE_MAX_CONNECT_TIMEOUT; x += PIPE_CONNECT_FAIL_REPEAT_DELAY)
{

h = CreateFile(
pipe_settings->name,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);

err = GetLastError();

if (h != INVALID_HANDLE_VALUE)
break;

if(err == ERROR_FILE_NOT_FOUND) {
//The pipe might not be open yet
sleep(PIPE_CONNECT_FAIL_REPEAT_DELAY/1000);
continue;
}

else if (err != ERROR_PIPE_BUSY) {
return err;
}

if (!WaitNamedPipe(pipe_settings->name, (DWORD)PIPE_MAX_CONNECT_TIMEOUT - x))
{
return ERROR_PIPE_BUSY;
}
}

if(h == INVALID_HANDLE_VALUE)
return err;

pipe_settings->hPipe = h;

DWORD dwMode = PIPE_READMODE_BYTE;

if(!SetNamedPipeHandleState(h, &dwMode, NULL, NULL))
return GetLastError();

return ERROR_SUCCESS;
}

DWORD PipeListenForServerConnect(struct pipe_settings *pipe_settings)
{
InitializePipeSettings(pipe_settings);

HANDLE hPipe = CreateNamedPipe(
pipe_settings->name,
PIPE_ACCESS_INBOUND | // read/write access
FILE_FLAG_OVERLAPPED, // overlapped mode
PIPE_TYPE_BYTE | // message-type pipe
PIPE_READMODE_BYTE | // message-read mode
PIPE_WAIT,
1,
PIPE_BUFFER_SIZE,
PIPE_BUFFER_SIZE,
PIPE_TIMEOUT,
NULL
);

if (hPipe == INVALID_HANDLE_VALUE)
{
return GetLastError();
}

OVERLAPPED ol;
//DWORD dwWait;

ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

if(ol.hEvent == NULL)
{
return GetLastError();
}

if(ConnectNamedPipe(hPipe, &ol) == 0)
{
//error should be ERROR_IO_PENDING or ERROR_PIPE_CONNECTED
DWORD err = GetLastError();

//wait for the connection event
if (err != ERROR_IO_PENDING && err != ERROR_PIPE_CONNECTED) {
if (WaitForSingleObject(ol.hEvent, pipe_settings->pipe_timeout) != WAIT_OBJECT_0) {
CloseHandle(hPipe);
CloseHandle(ol.hEvent);
return err;
}
}
}

pipe_settings->hPipe = hPipe;
pipe_settings->ol.Pointer = ol.Pointer;
pipe_settings->ol.Offset = ol.Offset;
pipe_settings->ol.Internal = ol.Internal;
pipe_settings->ol.hEvent = ol.hEvent;
pipe_settings->ol.InternalHigh = ol.InternalHigh;
pipe_settings->ol.OffsetHigh = ol.OffsetHigh;

return ERROR_SUCCESS;
}

DWORD WINAPI ClientProc(LPVOID)
{
struct pipe_settings pipe_settings;
pipe_settings.name = TEXT(DUST_TEST_PIPE_NAME);
pipe_settings.pipe_timeout = PIPE_TEST_TIMEOUT;

DWORD err = PipeListenForServerConnect(&pipe_settings);
//EXPECT_EQ((DWORD)ERROR_SUCCESS, err);

WINBOOL pipe_close_success = PipeClose(&pipe_settings);
//EXPECT_NE(1, pipe_close_success);

return 0;
}

DWORD WINAPI ServerProc(LPVOID)
{
struct pipe_settings pipe_settings;
pipe_settings.name = TEXT(DUST_TEST_PIPE_NAME);
pipe_settings.pipe_timeout = PIPE_TEST_TIMEOUT;

DWORD err = PipeConnectToClient(&pipe_settings);
//EXPECT_EQ((DWORD)ERROR_SUCCESS, err);

WINBOOL pipe_close_success = PipeClose(&pipe_settings);
//EXPECT_NE(0, pipe_close_success);

return 0;
}



int main(void) {

DWORD dwThreadId1;
DWORD dwThreadId2;

HANDLE h1 = CreateThread(NULL, 0, ServerProc, NULL, 0, &dwThreadId1);
HANDLE h2 = CreateThread(NULL, 0, ClientProc, NULL, 0, &dwThreadId2);

WaitForSingleObject(h1, INFINITE);
WaitForSingleObject(h2, INFINITE);
// your code goes here
return 0;
}

最佳答案

CreateEvent() 不使用 INVALID_HANDLE_VALUE 来表示无效句柄,而是使用 NULL 来代替。因此,您需要将 InitializePipeSettings() 初始化 ol.hEventNULL:

void InitializePipeSettings(struct pipe_settings *pipe_settings)
{
pipe_settings->hPipe = INVALID_HANDLE_VALUE;
pipe_settings->ol.hEvent = NULL; // <-- here
pipe_settings->ol.Internal = 0;
pipe_settings->ol.InternalHigh = 0;
pipe_settings->ol.Offset = 0;
pipe_settings->ol.OffsetHigh = 0;
pipe_settings->ol.Pointer = NULL;
}

然后在 PipeClose() 中,您需要在调用 CloseHandle()< 之前检查每个句柄是否有 INVALID_HANDLE_VALUE/NULL/ 就可以了。您还应该让 PipeClose() 重置其关闭的句柄,以便可以在同一个 pipe_settings 上安全地多次调用 PipeClose() >:

WINBOOL PipeClose(struct pipe_settings *pipe_settings)
{
BOOL bResult = TRUE;
if (pipe_settings->ol.hEvent != NULL)
{
bResult = bResult && CloseHandle(pipe_settings->ol.hEvent);
pipe_settings->ol.hEvent = NULL;
}
if (pipe_settings->hPipe != INVALID_HANDLE_VALUE)
{
bResult = bResult && CloseHandle(pipe_settings->hPipe);
pipe_settings->hPipe = INVALID_HANDLE_VALUE;
}
return bResult;
}

关于c - 开放管道上 CloseHandle 上的 sigsegv,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32189856/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com