From 2305a169809f7f7ff8429223a88922215f7775cc Mon Sep 17 00:00:00 2001 From: Manoj Ampalam Date: Mon, 7 Mar 2016 14:25:38 -0800 Subject: [PATCH] 3-7 C3 advancing file pointer in read completion routine --- contrib/win32/win32compat/fileio.c | 26 +++++++++++----------- contrib/win32/win32compat/w32fd.c | 18 +++++++-------- contrib/win32/win32compat/w32fd.h | 1 + regress/unittests/win32compat/file_tests.c | 13 ++++++++++- 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index 970b550..04f89a4 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -270,12 +270,13 @@ VOID CALLBACK ReadCompletionRoutine( pio->read_details.remaining = dwNumberOfBytesTransfered; pio->read_details.completed = 0; pio->read_details.pending = FALSE; + *((__int64*)&lpOverlapped->Offset) += dwNumberOfBytesTransfered; } /* initiate an async read */ int fileio_ReadFileEx(struct w32_io* pio) { - + HANDLE h = pio->handle; debug2("io:%p", pio); if (pio->read_details.buf == NULL){ pio->read_details.buf = malloc(READ_BUFFER_SIZE); @@ -287,7 +288,11 @@ fileio_ReadFileEx(struct w32_io* pio) { pio->read_details.buf_size = READ_BUFFER_SIZE; } - if (ReadFileEx(pio->handle, pio->read_details.buf, pio->read_details.buf_size, + /* get underlying handle for standard io */ + if (pio->type == STD_IO_FD) + h = GetStdHandle(pio->std_handle); + + if (ReadFileEx(h, pio->read_details.buf, pio->read_details.buf_size, &pio->read_overlapped, &ReadCompletionRoutine)) pio->read_details.pending = TRUE; else { @@ -325,16 +330,6 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) { } if (fileio_is_io_available(pio, TRUE) == FALSE) { - /* Workaround for - ReadFileEx is restting file pointer to beginning upon encoutering a EOF*/ - /* If there was a previous read and if the file pointer is at 0, then its been reset*/ - if ((pio->type == FILE_FD) && (pio->read_details.completed > 0)){ - LARGE_INTEGER to_move, new_fp; - to_move.QuadPart = 0; - if (SetFilePointerEx(pio->handle, to_move, &new_fp, FILE_CURRENT) && (new_fp.QuadPart == 0)) { - errno = 0; - return 0; - } - } if (-1 == fileio_ReadFileEx(pio)) { if ((pio->type == PIPE_FD) && (errno == ERROR_NEGATIVE_SEEK)) { /* write end of the pipe closed */ @@ -406,6 +401,7 @@ VOID CALLBACK WriteCompletionRoutine( int fileio_write(struct w32_io* pio, const void *buf, unsigned int max) { int bytes_copied; + HANDLE h = pio->handle; debug2("io:%p", pio); if ((pio->type == PIPE_FD) && (pio->internal.state == PIPE_READ_END)) { @@ -450,7 +446,11 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) { bytes_copied = min(max, pio->write_details.buf_size); memcpy(pio->write_details.buf, buf, bytes_copied); - if (WriteFileEx(pio->handle, pio->write_details.buf, bytes_copied, + /* get underlying handle for standard io */ + if (pio->type == STD_IO_FD) + h = GetStdHandle(pio->std_handle); + + if (WriteFileEx(h, pio->write_details.buf, bytes_copied, &pio->write_overlapped, &WriteCompletionRoutine)) { pio->write_details.pending = TRUE; /* execute APC if write has completed */ diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c index 4e43e3f..564be5e 100644 --- a/contrib/win32/win32compat/w32fd.c +++ b/contrib/win32/win32compat/w32fd.c @@ -24,21 +24,20 @@ static struct w32_io w32_io_stdin, w32_io_stdout, w32_io_stderr; void fd_table_set(struct w32_io* pio, int index); -#pragma warning(disable:4312) /* initializes mapping table*/ static int fd_table_initialize() { memset(&fd_table, 0, sizeof(fd_table)); memset(&w32_io_stdin, 0, sizeof(w32_io_stdin)); - w32_io_stdin.handle = (HANDLE)STD_INPUT_HANDLE; + w32_io_stdin.std_handle = STD_INPUT_HANDLE; w32_io_stdin.type = STD_IO_FD; fd_table_set(&w32_io_stdin, STDIN_FILENO); memset(&w32_io_stdout, 0, sizeof(w32_io_stdout)); - w32_io_stdout.handle = (HANDLE)STD_OUTPUT_HANDLE; + w32_io_stdout.std_handle = STD_OUTPUT_HANDLE; w32_io_stdout.type = STD_IO_FD; fd_table_set(&w32_io_stdout, STDOUT_FILENO); memset(&w32_io_stderr, 0, sizeof(w32_io_stderr)); - w32_io_stderr.handle = (HANDLE)STD_ERROR_HANDLE; + w32_io_stderr.std_handle = STD_ERROR_HANDLE; w32_io_stderr.type = STD_IO_FD; fd_table_set(&w32_io_stderr, STDERR_FILENO); return 0; @@ -425,7 +424,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep HANDLE events[SELECT_EVENT_LIMIT]; int num_events = 0; int in_set_fds = 0, out_ready_fds = 0, i; - unsigned int time_ms_rem = 0; + unsigned int timeout_ms = 0, time_rem = 0; errno = 0; /* TODO - the size of these can be reduced based on fds */ @@ -433,7 +432,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep memset(&write_ready_fds, 0, sizeof(w32_fd_set)); if (timeout) - time_ms_rem = timeout->tv_sec * 100 + timeout->tv_usec / 1000; + timeout_ms = timeout->tv_sec * 100 + timeout->tv_usec / 1000; if (fds > MAX_FDS) { errno = EINVAL; @@ -538,17 +537,18 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep /* wait for io if none is already ready */ while (out_ready_fds == 0) { ticks_spent = GetTickCount64() - ticks_start; + time_rem = 0; if (timeout != NULL) { - if (time_ms_rem < ticks_spent) { + if (timeout_ms < ticks_spent) { errno = ETIMEDOUT; debug("select timing out"); return -1; } - time_ms_rem -= ticks_spent & 0xffffffff; + time_rem = timeout_ms - (ticks_spent & 0xffffffff); } - if (0 != wait_for_any_event(events, num_events, time_ms_rem)) + if (0 != wait_for_any_event(events, num_events, time_rem)) return -1; /* check on fd status */ diff --git a/contrib/win32/win32compat/w32fd.h b/contrib/win32/win32compat/w32fd.h index 995cbe8..a91f137 100644 --- a/contrib/win32/win32compat/w32fd.h +++ b/contrib/win32/win32compat/w32fd.h @@ -71,6 +71,7 @@ struct w32_io { union { SOCKET sock; HANDLE handle; + DWORD std_handle; /* ex. STD_INPUT_HANDLE */ }; /*handle specific internal state context, used by sockets and pipes*/ diff --git a/regress/unittests/win32compat/file_tests.c b/regress/unittests/win32compat/file_tests.c index 22c1b3f..e83b505 100644 --- a/regress/unittests/win32compat/file_tests.c +++ b/regress/unittests/win32compat/file_tests.c @@ -224,12 +224,23 @@ file_select_tests() { } +void console_io_test() +{ + char tmp[10]; + TEST_START("console io test"); + ret = read(STDIN_FILENO, tmp, 10); + ret = write(STDOUT_FILENO, "sample output", 13); + ASSERT_INT_EQ(errno, 0); + ASSERT_INT_EQ(ret, 13); + TEST_DONE(); +} void file_tests() { w32posix_initialize(); - file_simple_fileio(); + //console_io_test(); + //file_simple_fileio(); file_blocking_io_tests(); file_nonblocking_io_tests(); file_select_tests();