From: Juergen Perlinger Date: Tue, 4 Oct 2016 06:36:17 +0000 (+0200) Subject: [Bug 3125] NTPD doesn't fully start when ntp.conf entries are out of order using... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=df80c411c27f8b07ded3973175992556efb13f1c;p=thirdparty%2Fntp.git [Bug 3125] NTPD doesn't fully start when ntp.conf entries are out of order using the loopback-ppsapi-provider.dll bk: 57f34de1Cp_P0NidT2Ym9FzsbNLtCA --- diff --git a/ChangeLog b/ChangeLog index 43e74b4c7..cf8174374 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,8 @@ * [Sec 3072] Attack on interface selection - implemented Miroslav Lichvars suggestion to skip interface updates based on incoming packets +* [Bug 3125] NTPD doesn't fully start when ntp.conf entries are out of order + using the loopback-ppsapi-provider.dll * [Bug 3116] unit tests for NTP time stamp expansion. * [Bug 3100] ntpq can't retrieve daemon_version - fixed extended sysvar lookup (bug introduced with bug 3008 fix) diff --git a/ports/winnt/include/ntp_iocompletionport.h b/ports/winnt/include/ntp_iocompletionport.h index a5558a0b8..b75c421c1 100644 --- a/ports/winnt/include/ntp_iocompletionport.h +++ b/ports/winnt/include/ntp_iocompletionport.h @@ -21,7 +21,7 @@ extern void io_completion_port_remove_interface(struct interface*); extern BOOL io_completion_port_add_socket(SOCKET fd, struct interface *, BOOL bcast); extern void io_completion_port_remove_socket(SOCKET fd, struct interface*); -extern int io_completion_port_sendto(struct interface*, SOCKET, void *, size_t, sockaddr_u *); +extern int io_completion_port_sendto(endpt*, SOCKET, void *, size_t, sockaddr_u *); extern BOOL io_completion_port_add_clock_io(struct refclockio *rio); extern void io_completion_port_remove_clock_io(struct refclockio *rio); diff --git a/ports/winnt/include/termios.h b/ports/winnt/include/termios.h index 94331afca..2ed342089 100644 --- a/ports/winnt/include/termios.h +++ b/ports/winnt/include/termios.h @@ -211,4 +211,7 @@ extern int tcgetattr (int, struct termios *); extern int tcflush (int, int); extern int isserialhandle (HANDLE); +typedef struct DeviceContext DevCtx_t; +extern DevCtx_t* serial_devctx(HANDLE); + #endif /* NTP_WIN_TERMIOS_H */ diff --git a/ports/winnt/libntp/termios.c b/ports/winnt/libntp/termios.c index 9596593b7..22b06b471 100644 --- a/ports/winnt/libntp/termios.c +++ b/ports/winnt/libntp/termios.c @@ -11,16 +11,135 @@ #include "ntp_assert.h" #include "win32_io.h" +#include "ntp_iocplmem.h" +#include "ntp_iocpltypes.h" + +/* ------------------------------------------------------------------- + * COM port management + * + * com port handling needs some special functionality, especially for + * PPS support. There are things that are shared by the Windows Kernel + * on device level, not handle level. These include IOCPL membership, + * event wait slot, ... It's also no so simple to open a device a + * second time, and so we must manage the handles on open com ports + * in userland. Well, partially. + */ #define MAX_SERIAL 255 /* COM1: - COM255: */ +#define MAX_COMDUP 8 /* max. allowed number of dupes per device */ typedef struct comhandles_tag { - HANDLE h; - size_t opens; - HANDLE * dupes; + uint16_t unit; /* COMPORT number */ + uint16_t nhnd; /* number of open handles */ + char * comName;/* windows device name */ + DevCtx_t * devCtx; /* shared device context */ + HANDLE htab[MAX_COMDUP]; /* OS handles */ } comhandles; -comhandles * hnds; /* handle/dupes array */ -size_t c_hnds; /* current array size */ +comhandles ** tab_comh; /* device data table */ +size_t num_comh; /* current used array size */ +size_t max_comh; /* current allocated array size */ + +/* lookup a COM unit by a handle + * Scans all used units for a matching handle. Returns the slot + * or NULL on failure. + * + * If 'phidx' is given, the index in the slots handle table that + * holds the handle is also returned. + * + * This a simple 2d table scan. But since we don't expect to have + * hundreds of com ports open, this should be no problem. + */ +static comhandles* +lookup_com_handle( + HANDLE h, + size_t * phidx + ) +{ + size_t tidx, hidx; + comhandles * slot; + for (tidx = 0; tidx < num_comh; ++tidx) { + slot = tab_comh[tidx]; + for (hidx = 0; hidx < slot->nhnd; ++hidx) { + if (slot->htab[hidx] == h) { + if (phidx != NULL) + *phidx = hidx; + return slot; + } + } + } + return NULL; +} + +/* lookup the list of COM units by unit number. This will always return + * a valid location -- eventually the table gets expanded, and a new + * entry is returned. In that case, the structure is set up with all + * entries valid and *no* file handles yet. + */ +static comhandles* +insert_com_unit( + uint16_t unit +) +{ + size_t tidx; + comhandles * slot; + + /* search for matching entry and return if found */ + for (tidx = 0; tidx < num_comh; ++tidx) + if (tab_comh[tidx]->unit == unit) + return tab_comh[tidx]; + + /* search failed. make sure we can add a new slot */ + if (num_comh >= max_comh) { + /* round up to next multiple of 4 */ + max_comh = (num_comh + 4) & ~(size_t)3; + tab_comh = erealloc(tab_comh, max_comh * sizeof(tab_comh[0])); + } + + /* create a new slot and populate it. */ + slot = emalloc_zero(sizeof(comhandles)); + LIB_GETBUF(slot->comName); + snprintf(slot->comName, LIB_BUFLENGTH, "\\\\.\\COM%d", unit); + slot->comName = estrdup(slot->comName); + slot->devCtx = DevCtxAlloc(); + slot->unit = unit; + + /* plug it into table and return it */ + tab_comh[num_comh++] = slot; + return slot; +} + +/* remove a COM slot from the table and destroy it. */ +static void +remove_com_slot( + comhandles * slot /* must be valid! */ + ) +{ + size_t tidx; + for (tidx = 0; tidx < num_comh; ++tidx) + if (tab_comh[tidx] == slot) { + tab_comh[tidx] = tab_comh[--num_comh]; + break; + } + + DevCtxDetach(slot->devCtx); + free(slot->comName); + free(slot); +} + +/* fetch the stored device context block. + * This does NOT step the reference counter! + */ +DevCtx_t* +serial_devctx( + HANDLE h + ) +{ + comhandles * slot = NULL; + if (INVALID_HANDLE_VALUE != h && NULL != h) + slot = lookup_com_handle(h, NULL); + return (NULL != slot) ? slot->devCtx : NULL; +} + /* * common_serial_open ensures duplicate opens of the same port @@ -30,16 +149,13 @@ size_t c_hnds; /* current array size */ HANDLE common_serial_open( const char * dev, - char ** pwindev + const char ** pwindev ) { - char * windev; HANDLE handle; size_t unit; - size_t prev_c_hnds; - size_t opens; const char * pch; - u_int uibuf; + comhandles * slot; /* * This is odd, but we'll take any unix device path @@ -55,147 +171,105 @@ common_serial_open( TRACE(1, ("common_serial_open given %s\n", dev)); + handle = INVALID_HANDLE_VALUE; + pch = NULL; if ('/' == dev[0]) { - pch = dev + strlen(dev) - 1; - - if (isdigit(pch[0])) { - while (isdigit(pch[0])) { - pch--; - } - pch++; - } + pch = dev + strlen(dev); + while (isdigit((u_char)pch[-1])) + --pch; TRACE(1, ("common_serial_open skipped to ending digits leaving %s\n", pch)); - } else if ('c' == tolower(dev[0]) - && 'o' == tolower(dev[1]) - && 'm' == tolower(dev[2])) { + } else if (0 == _strnicmp("COM", dev, 3)) { pch = dev + 3; TRACE(1, ("common_serial_open skipped COM leaving %s\n", pch)); } - if (!pch || !isdigit(pch[0])) { + if (!pch || !isdigit((u_char)pch[0])) { TRACE(1, ("not a digit: %s\n", pch ? pch : "[NULL]")); return INVALID_HANDLE_VALUE; } - if (1 != sscanf(pch, "%u", &uibuf) - || (unit = uibuf) > MAX_SERIAL) { - TRACE(1, ("sscanf failure of %s\n", pch)); + unit = strtoul(pch, (char**)&pch, 10); + if (*pch || unit > MAX_SERIAL) { + TRACE(1, ("conversion failure: unit=%u at '%s'\n", pch)); return INVALID_HANDLE_VALUE; } - - if (c_hnds < unit + 1) { - prev_c_hnds = c_hnds; - c_hnds = unit + 1; - /* round up to closest multiple of 4 to avoid churn */ - c_hnds = (c_hnds + 3) & ~3; - hnds = erealloc_zero(hnds, c_hnds * sizeof(hnds[0]), - prev_c_hnds * sizeof(hnds[0])); - } - - if (NULL == hnds[unit].h) { - INSIST(0 == hnds[unit].opens); - LIB_GETBUF(windev); - snprintf(windev, LIB_BUFLENGTH, "\\\\.\\COM%d", unit); - TRACE(1, ("windows device %s\n", windev)); - *pwindev = windev; - hnds[unit].h = - CreateFile( - windev, + /* Now.... find the COM slot, and either create a new file + * (if there is no handle yet) or duplicate one of the existing + * handles. Unless the dup table for one com port would overflow, + * but that's an indication of a programming error somewhere. + */ + slot = insert_com_unit(unit); + if (slot->nhnd == 0) { + TRACE(1, ("windows device %s\n", slot->comName)); + slot->htab[0] = CreateFileA( + slot->comName, GENERIC_READ | GENERIC_WRITE, 0, /* sharing prohibited */ NULL, /* default security */ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - if (INVALID_HANDLE_VALUE == hnds[unit].h) - hnds[unit].h = NULL; - } - - if (NULL != hnds[unit].h) { - /* think handle = dup(hnds[unit].h); */ - DuplicateHandle( - GetCurrentProcess(), - hnds[unit].h, - GetCurrentProcess(), - &handle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS - ); - hnds[unit].opens++; - opens = hnds[unit].opens; - hnds[unit].dupes = erealloc(hnds[unit].dupes, opens * - sizeof(hnds[unit].dupes[0])); - hnds[unit].dupes[opens - 1] = handle; - return handle; + if (INVALID_HANDLE_VALUE != slot->htab[0]) { + slot->nhnd = 1; + handle = slot->htab[0]; + *pwindev = slot->comName; + } + } else if (slot->nhnd >= MAX_COMDUP) { + SetLastError(ERROR_TOO_MANY_OPEN_FILES); + } else if (DuplicateHandle(GetCurrentProcess(), slot->htab[0], + GetCurrentProcess(), &slot->htab[slot->nhnd], + 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + handle = slot->htab[slot->nhnd++]; + *pwindev = slot->comName; } - return INVALID_HANDLE_VALUE; + return handle; } - /* * closeserial() is used in place of close by ntpd refclock I/O for ttys */ int -closeserial(int fd) +closeserial( + int fd + ) { HANDLE h; - BOOL found; - size_t u; - size_t d; + size_t hidx; + comhandles * slot; h = (HANDLE)_get_osfhandle(fd); - if (INVALID_HANDLE_VALUE == h) { - errno = EBADF; - return -1; - } + if (INVALID_HANDLE_VALUE == h) + goto onerror; - d = 0; /* silence potent. uninit. warning */ - found = FALSE; - for (u = 0; u < c_hnds; u++) { - for (d = 0; d < hnds[u].opens; d++) { - if (hnds[u].dupes[d] == h) { - found = TRUE; - break; - } - } - if (found) - break; - } - if (found) { - hnds[u].opens--; - if (d < hnds[u].opens) - memmove(&hnds[u].dupes[d], - &hnds[u].dupes[d + 1], - hnds[u].opens - d * - sizeof(hnds[u].dupes[d])); - if (0 == hnds[u].opens) { - CloseHandle(hnds[u].h); - hnds[u].h = NULL; - } - } + slot = lookup_com_handle(h, &hidx); + if (NULL == slot) + goto onerror; + + slot->htab[hidx] = slot->htab[--slot->nhnd]; + if (slot->nhnd == 0) + remove_com_slot(slot); + + return close(fd); /* closes system handle, too! */ - return close(fd); +onerror: + errno = EBADF; + return -1; } /* * isserialhandle() -- check if a handle is a COM port handle */ -int isserialhandle( +int/*BOOL*/ +isserialhandle( HANDLE h ) { - size_t u; - size_t d; - - - for (u = 0; u < c_hnds; u++) - for (d = 0; d < hnds[u].opens; d++) - if (hnds[u].dupes[d] == h) - return TRUE; + if (INVALID_HANDLE_VALUE != h && NULL != h) + return lookup_com_handle(h, NULL) != NULL; return FALSE; } @@ -206,23 +280,21 @@ int isserialhandle( * This routine opens a serial port for and returns the * file descriptor if success and -1 if failure. */ -int tty_open( +int +tty_open( const char *dev, /* device name pointer */ int access, /* O_RDWR */ int mode /* unused */ ) { - HANDLE Handle; - char * windev; + HANDLE Handle; + const char * windev; /* * open communication port handle */ - windev = NULL; + windev = dev; Handle = common_serial_open(dev, &windev); - windev = (windev) - ? windev - : dev; if (Handle == INVALID_HANDLE_VALUE) { msyslog(LOG_ERR, "tty_open: device %s CreateFile error: %m", windev); @@ -230,7 +302,7 @@ int tty_open( return -1; } - return (int)_open_osfhandle((intptr_t)Handle, _O_TEXT); + return _open_osfhandle((intptr_t)Handle, _O_TEXT); } @@ -247,7 +319,7 @@ refclock_open( u_int flags /* line discipline flags */ ) { - char * windev; + const char * windev; HANDLE h; COMMTIMEOUTS timeouts; DCB dcb; @@ -258,9 +330,8 @@ refclock_open( /* * open communication port handle */ - windev = NULL; + windev = dev; h = common_serial_open(dev, &windev); - windev = (windev) ? windev : dev; if (INVALID_HANDLE_VALUE == h) { SAVE_ERRNO( diff --git a/ports/winnt/ntpd/ntp_iocompletionport.c b/ports/winnt/ntpd/ntp_iocompletionport.c index 08f3c4e37..90bdd99e1 100644 --- a/ports/winnt/ntpd/ntp_iocompletionport.c +++ b/ports/winnt/ntpd/ntp_iocompletionport.c @@ -71,6 +71,11 @@ Juergen Perlinger (perlinger@ntp.org) Feb 2012 #define CONTAINEROF(p, type, member) \ ((type *)((char *)(p) - offsetof(type, member))) +enum io_packet_handling { + PKT_OK, + PKT_DROP, + PKT_SOCKET_ERROR +}; /* * local function definitions @@ -110,7 +115,7 @@ static HANDLE hMainThread; static BOOL DoPPShack; DWORD ActiveWaitHandles; -HANDLE WaitHandles[16]; +HANDLE WaitHandles[4]; /* @@ -474,6 +479,8 @@ IoResultCheck( const char * msg ) { + DPRINTF(6, ("in IoResultCheck err = %d\n", err)); + switch (err) { /* The first ones are no real errors. */ case ERROR_SUCCESS: /* all is good */ @@ -557,8 +564,7 @@ getRioFromIoCtx( static endpt* getEndptFromIoCtx( IoCtx_t * ctx, - ULONG_PTR key, - const char * msg + ULONG_PTR key ) { /* Make sure the key matches the context info in the shared @@ -570,7 +576,6 @@ getEndptFromIoCtx( * LSB is not used in the reverse-link check. Hence we shift * it out in both the input key and the registered source. */ - int oval, olen; /* getsockopt params */ endpt * ep = NULL; SharedLock_t * slock = slAttachShared(ctx->slock); if (slock != NULL) { @@ -581,7 +586,25 @@ getEndptFromIoCtx( ep = NULL; slDetachShared(slock); } - if (ep != NULL) switch (ctx->errCode) { + if (ep == NULL) + IoCtxRelease(ctx); + return ep; +} + + +static int +socketErrorCheck( + IoCtx_t * ctx, + const char * msg + ) +{ + int oval, olen; /* getsockopt params */ + int retCode; + + switch (ctx->errCode) { + case ERROR_SUCCESS: /* all is good */ + retCode = PKT_OK; + break; case ERROR_UNEXP_NET_ERR: if (hMainThread) QueueUserAPC(apcOnUnexpectedNetworkError, @@ -589,9 +612,7 @@ getEndptFromIoCtx( case ERROR_INVALID_PARAMETER: /* handle already closed (clock?)*/ case ERROR_OPERATION_ABORTED: /* handle closed while wait */ case WSAENOTSOCK : /* handle already closed (sock) */ - ctx->errCode = ERROR_SUCCESS; - ep = NULL; - case ERROR_SUCCESS: /* all is good */ + retCode = PKT_SOCKET_ERROR; break; /* [Bug 3019] is hard to squash. @@ -609,33 +630,35 @@ getEndptFromIoCtx( oval = 0; olen = sizeof(oval); getsockopt(ctx->io.sfd, SOL_SOCKET, SO_ERROR, (char*)&oval, &olen); - ctx->errCode = ERROR_SUCCESS; + retCode = PKT_DROP; break; /* [Bug 3110] On POSIX systems, reading UDP data into too small * a buffers silently truncates the message. Under Windows the * data is also truncated, but it blarts loudly about that. * Just pretend all is well, and all will be well. + * + * Note: We accept the truncated packet -- this is consistent with the + * POSIX / UNIX case where we have no notification about this at all. */ - case ERROR_MORE_DATA: - case WSAEMSGSIZE : - ctx->errCode = ERROR_SUCCESS; + case ERROR_MORE_DATA: /* Too Much data for Buffer */ + case WSAEMSGSIZE: + retCode = PKT_OK; /* or PKT_DROP ??? */ break; - /* For any other error, log the error, clear the byt count, but - * but return the endpoint. This prevents processing the packet - * and keeps the read-chain running -- otherwise NTPD will play + /* For any other error, log the error, clear the byte count, but + * return the endpoint. This prevents processing the packet and + * keeps the read-chain running -- otherwise NTPD will play * dead duck! */ default: LogIoError(msg, ctx->io.hnd, ctx->errCode); - ctx->byteCount = 0; + retCode = PKT_DROP; break; } - if (NULL == ep) - IoCtxRelease(ctx); - return ep; + return retCode; } + /* * ------------------------------------------------------------------- * Serial IO stuff @@ -909,8 +932,8 @@ wait_again: */ static DWORD WINAPI OnSerialReadWorker( -void * ctx -) + void * ctx + ) { IoCtx_t * lpo; SharedLock_t * slock; @@ -1182,58 +1205,16 @@ OnSerialWriteComplete( * ------------------------------------------------------------------- */ -/* The dummy read procedure is used for getting the device context - * into the IO completion thread, using the IO completion queue for - * transport. There are other ways to accomplish what we need here, - * but using the IO machine is handy and avoids a lot of trouble. - */ -static void -OnPpsDummyRead( - ULONG_PTR key, - IoCtx_t * lpo - ) -{ - RIO_t * rio; - - rio = (RIO_t *)key; - lpo->devCtx = DevCtxAttach(rio->device_ctx); - SetEvent(lpo->ppswake); -} - __declspec(dllexport) void* __stdcall ntp_pps_attach_device( HANDLE hndIo ) { - IoCtx_t myIoCtx; - HANDLE myEvt; - DevCtx_t * dev; - DWORD rc; + DevCtx_t * dev = NULL; - if (!isserialhandle(hndIo)) { + dev = DevCtxAttach(serial_devctx(hndIo)); + if ( NULL == dev) SetLastError(ERROR_INVALID_HANDLE); - return NULL; - } - - ZERO(myIoCtx); - dev = NULL; - myEvt = CreateEvent(NULL, FALSE, FALSE, NULL); - if (myEvt == NULL) - goto done; - - myIoCtx.ppswake = myEvt; - myIoCtx.onIoDone = OnPpsDummyRead; - rc = ReadFile(hndIo, &myIoCtx.byteCount, 0, - &myIoCtx.byteCount, &myIoCtx.ol); - if (!rc && (GetLastError() != ERROR_IO_PENDING)) - goto done; - if (WaitForSingleObject(myEvt, INFINITE) == WAIT_OBJECT_0) - if (NULL == (dev = myIoCtx.devCtx)) - SetLastError(ERROR_INVALID_HANDLE); -done: - rc = GetLastError(); - CloseHandle(myEvt); - SetLastError(rc); return dev; } @@ -1332,7 +1313,7 @@ io_completion_port_add_clock_io( slock->riofd = rio->fd; slock->rsrc.rio = rio; - if ( ! (rio->device_ctx = DevCtxAlloc())) { + if (!(rio->device_ctx = DevCtxAttach(serial_devctx(h)))) { msyslog(LOG_ERR, "%s: Failed to allocate device context", msgh); goto fail; @@ -1435,9 +1416,13 @@ OnSocketRecv( recvbuf_t * buff = NULL; SharedLock_t * slock = NULL; + BOOL epOK = TRUE; + int retCode = PKT_OK; /* Make sure this endpoint is not closed. */ - endpt * ep = getEndptFromIoCtx(lpo, key, msg); + endpt * ep = getEndptFromIoCtx(lpo, key); + retCode = socketErrorCheck(lpo, msg); + if (ep == NULL) return; @@ -1448,7 +1433,7 @@ OnSocketRecv( * We also need an extra hold to the SLOCK structure. */ slock = slAttach(lpo->slock); - if (lpo->errCode == ERROR_SUCCESS && lpo->byteCount > 0) { + if (retCode == PKT_OK && lpo->byteCount > 0) { /* keep input buffer, create new one for IO */ buff = lpo->recv_buf; lpo->recv_buf = get_free_recv_buffer_alloc(); @@ -1457,7 +1442,13 @@ OnSocketRecv( buff->recv_length = (int)lpo->byteCount; } /* Note: else we use the current buffer again */ - IoCtxStartLocked(lpo, QueueSocketRecv, lpo->recv_buf); + + if (retCode != PKT_SOCKET_ERROR) { + IoCtxStartLocked(lpo, QueueSocketRecv, lpo->recv_buf); + } else { + freerecvbuf(lpo->recv_buf); + IoCtxFree(lpo); + } /* below this, any usage of 'lpo' is invalid! */ /* If we have a buffer, do some bookkeeping and other chores, @@ -1474,19 +1465,19 @@ OnSocketRecv( get_packet_mode(buff))); if (slAttachShared(slock)) { - BOOL epOK = slEndPointOK(slock); - if (epOK) - InterlockedIncrement(&slock->rsrc.ept->received); - slDetachShared(slock); - if (epOK) { + if (slEndPointOK(slock)) { + InterlockedIncrement(&ep->received); + slDetachShared(slock); InterlockedIncrement(&packets_received); InterlockedIncrement(&handler_pkts); + } else { + slDetachShared(slock); } } - DPRINTF(2, ("Received %d bytes fd %d in buffer %p from %s\n", + DPRINTF(2, ("Received %d bytes fd %d in buffer %p from %s, state = %s\n", buff->recv_length, (int)buff->fd, buff, - stoa(&buff->recv_srcadr))); + stoa(&buff->recv_srcadr), epOK? "Accepted" : "Ignored")); slQueueLocked(slock, slEndPointOK, buff); } slDetach(slock); @@ -1501,26 +1492,27 @@ OnSocketSend( { /* this is somewhat easier: */ static const char * const msg = - "OnSocketRecv: send to socket failed"; + "OnSocketSend: send to socket failed"; SharedLock_t * slock = NULL; - endpt * ep = getEndptFromIoCtx(lpo, key, msg); + endpt * ep = getEndptFromIoCtx(lpo, key); + int retCode = socketErrorCheck(lpo, msg); /* Make sure this endpoint is not closed. */ if (ep == NULL) return; - if (lpo->errCode != ERROR_SUCCESS) + if (retCode != PKT_OK) { slock = slAttachShared(lpo->slock); - if (slock) { - BOOL epOK = slEndPointOK(slock); - if (epOK) { - InterlockedIncrement(&slock->rsrc.ept->notsent); - InterlockedDecrement(&slock->rsrc.ept->sent); - } - slDetachShared(slock); - if (epOK) { - InterlockedIncrement(&packets_notsent); - InterlockedDecrement(&packets_sent); + if (slock) { + if (slEndPointOK(slock)) { + InterlockedIncrement(&ep->notsent); + InterlockedDecrement(&ep->sent); + slDetachShared(slock); + InterlockedIncrement(&packets_notsent); + InterlockedDecrement(&packets_sent); + } else { + slDetachShared(slock); + } } } IoCtxRelease(lpo); @@ -1721,7 +1713,10 @@ GetReceivedBuffers(void) { DWORD index; HANDLE ready; - int have_packet; + int errcode; + BOOL dynbuf; + BOOL have_packet; + char * msgbuf; have_packet = FALSE; while (!have_packet) { @@ -1748,20 +1743,18 @@ GetReceivedBuffers(void) case WAIT_TIMEOUT: msyslog(LOG_ERR, - "WaitForMultipleObjects INFINITE timed out."); - exit(1); + "WaitForMultipleObjectsEx INFINITE timed out."); break; case WAIT_FAILED: - { - BOOL dynbuf = FALSE; - char * msgbuf = NTstrerror(GetLastError(), &dynbuf); + dynbuf = FALSE; + errcode = GetLastError(); + msgbuf = NTstrerror(errcode, &dynbuf); msyslog(LOG_ERR, - "WaitForMultipleObjects Failed: Error: %s", msgbuf); + "WaitForMultipleObjectsEx Failed: Errcode = %n, msg = %s", errcode, msgbuf); if (dynbuf) LocalFree(msgbuf); exit(1); - } break; default: diff --git a/ports/winnt/ntpd/ntp_iocpltypes.c b/ports/winnt/ntpd/ntp_iocpltypes.c index bd12f2881..538217a7b 100644 --- a/ports/winnt/ntpd/ntp_iocpltypes.c +++ b/ports/winnt/ntpd/ntp_iocpltypes.c @@ -211,10 +211,10 @@ DevCtxAlloc(void) /* allocate struct and tag all slots as invalid */ devCtx = (DevCtx_t *)IOCPLPoolAlloc(sizeof(DevCtx_t), "DEV ctx"); if (devCtx != NULL) { + devCtx->ref_count = 1; /* already owned! */ /* The initial COV values make sure there is no busy * loop on unused/empty slots. */ - devCtx->cov_count = 1; /* already owned! */ for (slot = 0; slot < PPS_QUEUE_LEN; slot++) devCtx->pps_buff[slot].cov_count = ~slot; } @@ -299,7 +299,7 @@ IoCtxRelease( ) { static const char *const dmsg = - "overlapped IO data buffer"; + "Release overlapped IO data buffer"; if (ctx) { if (ctx->flRawMem)