Здравствуйте, acDev, Вы писали:
D>Здравствуйте, remark, Вы писали:
R>> OVERLAPPED ol = {};
R>> cancel_t can = {c, &ol};
R>> HANDLE ct = (HANDLE)_beginthreadex(0, 0, canceler, &can, 0, 0);
R>> for(;) {
R>> WSABUF b;
R>> b.buf = (char*)buf;
R>> b.len = recvbuf;
R>> DWORD recv = 0, flags = 0;
R>> if(WSARecv(c, &b, 1, &recv, &flags, &ol, 0) == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
R>> panic("WSARecv");
R>> if(!WSAGetOverlappedResult(c, &ol, &recv, 1, &flags)) {
R>>static unsigned __stdcall
R>>canceler(void *arg)
R>>{
R>> cancel_t *can = (cancel_t*)arg;
R>> for(;) {
R>> Sleep(0);
R>> if(!CancelIoEx((HANDLE)can->c, can->ol)) {
D>Почему в структуре OVERLAPPED поле hEvent не определено?
Его разве обязательно определять? WSAGetOverlappedResult() может работать без него, тогда он смотрит на "состояние дескриптора". В боевой программе используется GQCS, которому тоже не нужен евент.
D>Почему структура OVERLAPPED одновременно используется в двух потоках?
Потому что так происходит в боевой программе. Это нормально, т.к. CancelIoEx предназначена для отмены операций, запущенных в других потоках.
D>И что вы этим кодом вообще хотели добиться?
Это минимальный репродьюсер проблемы из большой программы.
Это не так важно. Важно — должна ли эта, пусть и глупая, программа работать или нет? Глупая программа не должна вешать ядро и приводить к BSOD, правильно?
Большая программа — это рантайм языка Go:
https://code.google.com/p/go/source/browse/src/pkg/net/fd_windows.go
https://code.google.com/p/go/source/browse/src/pkg/runtime/netpoll_windows.c
https://code.google.com/p/go/source/browse/src/pkg/runtime/netpoll.goc
Но в нём сложно разбираться.