mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* win32/win32.c, include/ruby/win32.h (rb_w32_open): overlapped file
I/O support. * win32/win32.c, include/ruby/win32.h (rb_w32_pipe): overlapped pipe I/O support. * wn32/win32.c (rb_w32_read, rb_w32_write): overlapped I/O support to enable canceling I/O. * thread_win32.c (ubf_handle): remove workaround. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18897 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
cf6334e1cb
commit
3c8dca55c4
4 changed files with 466 additions and 20 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
Thu Aug 28 21:43:05 2008 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||||
|
|
||||||
|
* win32/win32.c, include/ruby/win32.h (rb_w32_open): overlapped file
|
||||||
|
I/O support.
|
||||||
|
|
||||||
|
* win32/win32.c, include/ruby/win32.h (rb_w32_pipe): overlapped pipe
|
||||||
|
I/O support.
|
||||||
|
|
||||||
|
* wn32/win32.c (rb_w32_read, rb_w32_write): overlapped I/O support to
|
||||||
|
enable canceling I/O.
|
||||||
|
|
||||||
|
* thread_win32.c (ubf_handle): remove workaround.
|
||||||
|
|
||||||
Thu Aug 28 20:22:49 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
|
Thu Aug 28 20:22:49 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
* vm_insnhelper.c (vm_yield_setup_args): object with to_ary should
|
* vm_insnhelper.c (vm_yield_setup_args): object with to_ary should
|
||||||
|
|
|
@ -134,7 +134,8 @@ extern DWORD rb_w32_osid(void);
|
||||||
#define utime(_p, _t) rb_w32_utime(_p, _t)
|
#define utime(_p, _t) rb_w32_utime(_p, _t)
|
||||||
#define lseek(_f, _o, _w) _lseeki64(_f, _o, _w)
|
#define lseek(_f, _o, _w) _lseeki64(_f, _o, _w)
|
||||||
|
|
||||||
#define pipe(p) _pipe(p, 65536L, _O_NOINHERIT)
|
#define pipe(p) rb_w32_pipe(p)
|
||||||
|
#define open rb_w32_open
|
||||||
#define close(h) rb_w32_close(h)
|
#define close(h) rb_w32_close(h)
|
||||||
#define fclose(f) rb_w32_fclose(f)
|
#define fclose(f) rb_w32_fclose(f)
|
||||||
#define read(f, b, s) rb_w32_read(f, b, s)
|
#define read(f, b, s) rb_w32_read(f, b, s)
|
||||||
|
@ -543,8 +544,10 @@ HANDLE GetCurrentThreadHandle(void);
|
||||||
int rb_w32_sleep(unsigned long msec);
|
int rb_w32_sleep(unsigned long msec);
|
||||||
int rb_w32_putc(int, FILE*);
|
int rb_w32_putc(int, FILE*);
|
||||||
int rb_w32_getc(FILE*);
|
int rb_w32_getc(FILE*);
|
||||||
|
int rb_w32_open(const char *, int, ...);
|
||||||
int rb_w32_close(int);
|
int rb_w32_close(int);
|
||||||
int rb_w32_fclose(FILE*);
|
int rb_w32_fclose(FILE*);
|
||||||
|
int rb_w32_pipe(int[2]);
|
||||||
size_t rb_w32_read(int, void *, size_t);
|
size_t rb_w32_read(int, void *, size_t);
|
||||||
size_t rb_w32_write(int, const void *, size_t);
|
size_t rb_w32_write(int, const void *, size_t);
|
||||||
int rb_w32_utime(const char *, const struct utimbuf *);
|
int rb_w32_utime(const char *, const struct utimbuf *);
|
||||||
|
|
|
@ -524,18 +524,9 @@ static void
|
||||||
ubf_handle(void *ptr)
|
ubf_handle(void *ptr)
|
||||||
{
|
{
|
||||||
typedef BOOL (WINAPI *cancel_io_func_t)(HANDLE);
|
typedef BOOL (WINAPI *cancel_io_func_t)(HANDLE);
|
||||||
static cancel_io_func_t cancel_func = NULL;
|
|
||||||
rb_thread_t *th = (rb_thread_t *)ptr;
|
rb_thread_t *th = (rb_thread_t *)ptr;
|
||||||
thread_debug("ubf_handle: %p\n", th);
|
thread_debug("ubf_handle: %p\n", th);
|
||||||
|
|
||||||
if (!cancel_func) {
|
|
||||||
cancel_func = (cancel_io_func_t)GetProcAddress(GetModuleHandle("kernel32"), "CancelSynchronousIo");
|
|
||||||
if (!cancel_func)
|
|
||||||
cancel_func = (cancel_io_func_t)-1;
|
|
||||||
}
|
|
||||||
if (cancel_func != (cancel_io_func_t)-1)
|
|
||||||
cancel_func((HANDLE)th->thread_id);
|
|
||||||
|
|
||||||
w32_set_event(th->native_thread_data.interrupt_event);
|
w32_set_event(th->native_thread_data.interrupt_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
459
win32/win32.c
459
win32/win32.c
|
@ -1736,6 +1736,8 @@ set_pioinfo_extra(void)
|
||||||
#define _set_osflags(fh, flags) (_osfile(fh) = (flags))
|
#define _set_osflags(fh, flags) (_osfile(fh) = (flags))
|
||||||
|
|
||||||
#define FOPEN 0x01 /* file handle open */
|
#define FOPEN 0x01 /* file handle open */
|
||||||
|
#define FEOFLAG 0x02 /* end of file has been encountered */
|
||||||
|
#define FPIPE 0x08 /* file handle refers to a pipe */
|
||||||
#define FNOINHERIT 0x10 /* file handle opened O_NOINHERIT */
|
#define FNOINHERIT 0x10 /* file handle opened O_NOINHERIT */
|
||||||
#define FAPPEND 0x20 /* file handle opened O_APPEND */
|
#define FAPPEND 0x20 /* file handle opened O_APPEND */
|
||||||
#define FDEV 0x40 /* file handle refers to device */
|
#define FDEV 0x40 /* file handle refers to device */
|
||||||
|
@ -3994,6 +3996,167 @@ rb_w32_getppid(void)
|
||||||
return ppid;
|
return ppid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_w32_open(const char *file, int oflag, ...)
|
||||||
|
{
|
||||||
|
char flags = 0;
|
||||||
|
int fd;
|
||||||
|
DWORD access;
|
||||||
|
DWORD create;
|
||||||
|
DWORD attr = FILE_ATTRIBUTE_NORMAL;
|
||||||
|
SECURITY_ATTRIBUTES sec;
|
||||||
|
HANDLE h;
|
||||||
|
|
||||||
|
sec.nLength = sizeof(sec);
|
||||||
|
sec.lpSecurityDescriptor = NULL;
|
||||||
|
if (oflag & O_NOINHERIT) {
|
||||||
|
sec.bInheritHandle = FALSE;
|
||||||
|
flags |= FNOINHERIT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sec.bInheritHandle = TRUE;
|
||||||
|
}
|
||||||
|
oflag &= ~O_NOINHERIT;
|
||||||
|
|
||||||
|
/* always open with binary mode */
|
||||||
|
oflag &= ~(O_BINARY | O_TEXT);
|
||||||
|
|
||||||
|
switch (oflag & (O_RDWR | O_RDONLY | O_WRONLY)) {
|
||||||
|
case O_RDWR:
|
||||||
|
access = GENERIC_READ | GENERIC_WRITE;
|
||||||
|
break;
|
||||||
|
case O_RDONLY:
|
||||||
|
access = GENERIC_READ;
|
||||||
|
break;
|
||||||
|
case O_WRONLY:
|
||||||
|
access = GENERIC_WRITE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
oflag &= ~(O_RDWR | O_RDONLY | O_WRONLY);
|
||||||
|
|
||||||
|
switch (oflag & (O_CREAT | O_EXCL | O_TRUNC)) {
|
||||||
|
case O_CREAT:
|
||||||
|
create = OPEN_ALWAYS;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
case O_EXCL:
|
||||||
|
create = OPEN_EXISTING;
|
||||||
|
break;
|
||||||
|
case O_CREAT | O_EXCL:
|
||||||
|
case O_CREAT | O_EXCL | O_TRUNC:
|
||||||
|
create = CREATE_NEW;
|
||||||
|
break;
|
||||||
|
case O_TRUNC:
|
||||||
|
case O_TRUNC | O_EXCL:
|
||||||
|
create = TRUNCATE_EXISTING;
|
||||||
|
break;
|
||||||
|
case O_CREAT | O_TRUNC:
|
||||||
|
create = CREATE_ALWAYS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (oflag & O_CREAT) {
|
||||||
|
va_list arg;
|
||||||
|
int pmode;
|
||||||
|
va_start(arg, oflag);
|
||||||
|
pmode = va_arg(arg, int);
|
||||||
|
va_end(arg);
|
||||||
|
/* TODO: we need to check umask here, but it's not exported... */
|
||||||
|
if (!(pmode & S_IWRITE))
|
||||||
|
attr = FILE_ATTRIBUTE_READONLY;
|
||||||
|
}
|
||||||
|
oflag &= ~(O_CREAT | O_EXCL | O_TRUNC);
|
||||||
|
|
||||||
|
if (oflag & O_TEMPORARY) {
|
||||||
|
attr |= FILE_FLAG_DELETE_ON_CLOSE;
|
||||||
|
access |= DELETE;
|
||||||
|
}
|
||||||
|
oflag &= ~O_TEMPORARY;
|
||||||
|
|
||||||
|
if (oflag & _O_SHORT_LIVED)
|
||||||
|
attr |= FILE_ATTRIBUTE_TEMPORARY;
|
||||||
|
oflag &= ~_O_SHORT_LIVED;
|
||||||
|
|
||||||
|
switch (oflag & (O_SEQUENTIAL | O_RANDOM)) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case O_SEQUENTIAL:
|
||||||
|
attr |= FILE_FLAG_SEQUENTIAL_SCAN;
|
||||||
|
break;
|
||||||
|
case O_RANDOM:
|
||||||
|
attr |= FILE_FLAG_RANDOM_ACCESS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
oflag &= ~(O_SEQUENTIAL | O_RANDOM);
|
||||||
|
|
||||||
|
if (oflag & ~O_APPEND) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate a C Runtime file handle */
|
||||||
|
RUBY_CRITICAL({
|
||||||
|
h = CreateFile("NUL", 0, 0, NULL, OPEN_ALWAYS, 0, NULL);
|
||||||
|
fd = _open_osfhandle((long)h, 0);
|
||||||
|
CloseHandle(h);
|
||||||
|
});
|
||||||
|
if (fd == -1) {
|
||||||
|
errno = EMFILE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
RUBY_CRITICAL({
|
||||||
|
MTHREAD_ONLY(EnterCriticalSection(&(_pioinfo(fd)->lock)));
|
||||||
|
_set_osfhnd(fd, (long)INVALID_HANDLE_VALUE);
|
||||||
|
_set_osflags(fd, 0);
|
||||||
|
|
||||||
|
/* open with FILE_FLAG_OVERLAPPED if have CancelIo */
|
||||||
|
if (cancel_io)
|
||||||
|
attr |= FILE_FLAG_OVERLAPPED;
|
||||||
|
h = CreateFile(file, access, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec,
|
||||||
|
create, attr, NULL);
|
||||||
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
fd = -1;
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (GetFileType(h)) {
|
||||||
|
case FILE_TYPE_CHAR:
|
||||||
|
flags |= FDEV;
|
||||||
|
break;
|
||||||
|
case FILE_TYPE_PIPE:
|
||||||
|
flags |= FPIPE;
|
||||||
|
break;
|
||||||
|
case FILE_TYPE_UNKNOWN:
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
CloseHandle(h);
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
fd = -1;
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
if (!(flags & (FDEV | FPIPE)) && (oflag & O_APPEND))
|
||||||
|
flags |= FAPPEND;
|
||||||
|
|
||||||
|
_set_osfhnd(fd, (long)h);
|
||||||
|
_osfile(fd) = flags | FOPEN;
|
||||||
|
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
quit:
|
||||||
|
;
|
||||||
|
});
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_w32_fclose(FILE *fp)
|
rb_w32_fclose(FILE *fp)
|
||||||
{
|
{
|
||||||
|
@ -4016,6 +4179,98 @@ rb_w32_fclose(FILE *fp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_w32_pipe(int fds[2])
|
||||||
|
{
|
||||||
|
static DWORD serial = 0;
|
||||||
|
char name[] = "\\\\.\\pipe\\ruby0000000000000000-0000000000000000";
|
||||||
|
char *p;
|
||||||
|
SECURITY_ATTRIBUTES sec;
|
||||||
|
HANDLE hRead, hWrite, h;
|
||||||
|
int fdRead, fdWrite;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* if doesn't have CancelIo, use default pipe function */
|
||||||
|
if (!cancel_io)
|
||||||
|
return _pipe(fds, 65536L, _O_NOINHERIT);
|
||||||
|
|
||||||
|
p = strchr(name, '0');
|
||||||
|
snprintf(p, strlen(p) + 1, "%x-%x", rb_w32_getpid(), serial++);
|
||||||
|
|
||||||
|
sec.nLength = sizeof(sec);
|
||||||
|
sec.lpSecurityDescriptor = NULL;
|
||||||
|
sec.bInheritHandle = FALSE;
|
||||||
|
|
||||||
|
RUBY_CRITICAL({
|
||||||
|
hRead = CreateNamedPipe(name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
||||||
|
0, 2, 65536, 65536, 0, &sec);
|
||||||
|
});
|
||||||
|
if (hRead == INVALID_HANDLE_VALUE) {
|
||||||
|
DWORD err = GetLastError();
|
||||||
|
if (err == ERROR_PIPE_BUSY)
|
||||||
|
errno = EMFILE;
|
||||||
|
else
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
RUBY_CRITICAL({
|
||||||
|
hWrite = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, &sec,
|
||||||
|
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||||
|
});
|
||||||
|
if (hWrite == INVALID_HANDLE_VALUE) {
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
CloseHandle(hRead);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
RUBY_CRITICAL(do {
|
||||||
|
ret = 0;
|
||||||
|
h = CreateFile("NUL", 0, 0, NULL, OPEN_ALWAYS, 0, NULL);
|
||||||
|
fdRead = _open_osfhandle((long)h, 0);
|
||||||
|
CloseHandle(h);
|
||||||
|
if (fdRead == -1) {
|
||||||
|
errno = EMFILE;
|
||||||
|
CloseHandle(hWrite);
|
||||||
|
CloseHandle(hRead);
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTHREAD_ONLY(EnterCriticalSection(&(_pioinfo(fdRead)->lock)));
|
||||||
|
_set_osfhnd(fdRead, (long)hRead);
|
||||||
|
_set_osflags(fdRead, FOPEN | FPIPE | FNOINHERIT);
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&(_pioinfo(fdRead)->lock)));
|
||||||
|
} while (0));
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
RUBY_CRITICAL(do {
|
||||||
|
h = CreateFile("NUL", 0, 0, NULL, OPEN_ALWAYS, 0, NULL);
|
||||||
|
fdWrite = _open_osfhandle((long)h, 0);
|
||||||
|
CloseHandle(h);
|
||||||
|
if (fdWrite == -1) {
|
||||||
|
errno = EMFILE;
|
||||||
|
CloseHandle(hWrite);
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MTHREAD_ONLY(EnterCriticalSection(&(_pioinfo(fdWrite)->lock)));
|
||||||
|
_set_osfhnd(fdWrite, (long)hWrite);
|
||||||
|
_set_osflags(fdWrite, FOPEN | FPIPE | FNOINHERIT);
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&(_pioinfo(fdWrite)->lock)));
|
||||||
|
} while (0));
|
||||||
|
if (ret) {
|
||||||
|
rb_w32_close(fdRead);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
fds[0] = fdRead;
|
||||||
|
fds[1] = fdWrite;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_w32_close(int fd)
|
rb_w32_close(int fd)
|
||||||
{
|
{
|
||||||
|
@ -4045,11 +4300,107 @@ size_t
|
||||||
rb_w32_read(int fd, void *buf, size_t size)
|
rb_w32_read(int fd, void *buf, size_t size)
|
||||||
{
|
{
|
||||||
SOCKET sock = TO_SOCKET(fd);
|
SOCKET sock = TO_SOCKET(fd);
|
||||||
|
DWORD read;
|
||||||
|
DWORD wait;
|
||||||
|
DWORD err;
|
||||||
|
OVERLAPPED ol, *pol = NULL;
|
||||||
|
|
||||||
if (!is_socket(sock))
|
if (is_socket(sock))
|
||||||
return read(fd, buf, size);
|
|
||||||
else
|
|
||||||
return rb_w32_recv(fd, buf, size, 0);
|
return rb_w32_recv(fd, buf, size, 0);
|
||||||
|
|
||||||
|
if (!(_osfile(fd) & FOPEN)) {
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTHREAD_ONLY(EnterCriticalSection(&(_pioinfo(fd)->lock)));
|
||||||
|
|
||||||
|
if (!size || _osfile(fd) & FEOFLAG) {
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if have cancel_io, use Overlapped I/O */
|
||||||
|
if (cancel_io) {
|
||||||
|
memset(&ol, 0, sizeof(ol));
|
||||||
|
if (!(_osfile(fd) & (FDEV | FPIPE))) {
|
||||||
|
LONG high = 0;
|
||||||
|
DWORD low = SetFilePointer((HANDLE)_osfhnd(fd), 0, &high,
|
||||||
|
FILE_CURRENT);
|
||||||
|
#ifndef INVALID_SET_FILE_POINTER
|
||||||
|
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
||||||
|
#endif
|
||||||
|
if (low == INVALID_SET_FILE_POINTER) {
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ol.Offset = low;
|
||||||
|
ol.OffsetHigh = high;
|
||||||
|
}
|
||||||
|
ol.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||||
|
if (!ol.hEvent) {
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pol = &ol;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ReadFile((HANDLE)_osfhnd(fd), buf, size, &read, pol)) {
|
||||||
|
err = GetLastError();
|
||||||
|
if (err != ERROR_IO_PENDING) {
|
||||||
|
if (err == ERROR_ACCESS_DENIED)
|
||||||
|
errno = EBADF;
|
||||||
|
else if (err == ERROR_BROKEN_PIPE) {
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
errno = map_errno(err);
|
||||||
|
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pol) {
|
||||||
|
wait = rb_w32_wait_events_blocking(&ol.hEvent, 1, INFINITE);
|
||||||
|
if (wait != WAIT_OBJECT_0) {
|
||||||
|
if (errno != EINTR)
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
CloseHandle(ol.hEvent);
|
||||||
|
cancel_io((HANDLE)_osfhnd(fd));
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetOverlappedResult((HANDLE)_osfhnd(fd), &ol, &read, TRUE) &&
|
||||||
|
(err = GetLastError()) != ERROR_HANDLE_EOF) {
|
||||||
|
errno = map_errno(err);
|
||||||
|
CloseHandle(ol.hEvent);
|
||||||
|
cancel_io((HANDLE)_osfhnd(fd));
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pol) {
|
||||||
|
CloseHandle(ol.hEvent);
|
||||||
|
|
||||||
|
if (!(_osfile(fd) & (FDEV | FPIPE))) {
|
||||||
|
LONG high = ol.OffsetHigh;
|
||||||
|
LONG low = ol.Offset + read;
|
||||||
|
if (low < ol.Offset)
|
||||||
|
++high;
|
||||||
|
SetFilePointer((HANDLE)_osfhnd(fd), low, &high, FILE_BEGIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
|
||||||
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef write
|
#undef write
|
||||||
|
@ -4057,15 +4408,103 @@ size_t
|
||||||
rb_w32_write(int fd, const void *buf, size_t size)
|
rb_w32_write(int fd, const void *buf, size_t size)
|
||||||
{
|
{
|
||||||
SOCKET sock = TO_SOCKET(fd);
|
SOCKET sock = TO_SOCKET(fd);
|
||||||
|
DWORD written;
|
||||||
|
DWORD wait;
|
||||||
|
DWORD err;
|
||||||
|
OVERLAPPED ol, *pol = NULL;
|
||||||
|
|
||||||
if (!is_socket(sock)) {
|
if (is_socket(sock))
|
||||||
size_t ret = write(fd, buf, size);
|
|
||||||
if ((int)ret < 0 && errno == EINVAL)
|
|
||||||
errno = map_errno(GetLastError());
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return rb_w32_send(fd, buf, size, 0);
|
return rb_w32_send(fd, buf, size, 0);
|
||||||
|
|
||||||
|
if (!(_osfile(fd) & FOPEN)) {
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTHREAD_ONLY(EnterCriticalSection(&(_pioinfo(fd)->lock)));
|
||||||
|
|
||||||
|
if (!size || _osfile(fd) & FEOFLAG) {
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if have cancel_io, use Overlapped I/O */
|
||||||
|
if (cancel_io) {
|
||||||
|
memset(&ol, 0, sizeof(ol));
|
||||||
|
if (!(_osfile(fd) & (FDEV | FPIPE))) {
|
||||||
|
LONG high = 0;
|
||||||
|
DWORD low = SetFilePointer((HANDLE)_osfhnd(fd), 0, &high,
|
||||||
|
FILE_CURRENT);
|
||||||
|
#ifndef INVALID_SET_FILE_POINTER
|
||||||
|
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
||||||
|
#endif
|
||||||
|
if (low == INVALID_SET_FILE_POINTER) {
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ol.Offset = low;
|
||||||
|
ol.OffsetHigh = high;
|
||||||
|
}
|
||||||
|
ol.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||||
|
if (!ol.hEvent) {
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pol = &ol;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WriteFile((HANDLE)_osfhnd(fd), buf, size, &written, pol)) {
|
||||||
|
err = GetLastError();
|
||||||
|
if (err != ERROR_IO_PENDING) {
|
||||||
|
if (err == ERROR_ACCESS_DENIED)
|
||||||
|
errno = EBADF;
|
||||||
|
else
|
||||||
|
errno = map_errno(err);
|
||||||
|
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pol) {
|
||||||
|
wait = rb_w32_wait_events_blocking(&ol.hEvent, 1, INFINITE);
|
||||||
|
if (wait != WAIT_OBJECT_0) {
|
||||||
|
if (errno != EINTR)
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
CloseHandle(ol.hEvent);
|
||||||
|
cancel_io((HANDLE)_osfhnd(fd));
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetOverlappedResult((HANDLE)_osfhnd(fd), &ol, &written,
|
||||||
|
TRUE)) {
|
||||||
|
errno = map_errno(err);
|
||||||
|
CloseHandle(ol.hEvent);
|
||||||
|
cancel_io((HANDLE)_osfhnd(fd));
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pol) {
|
||||||
|
CloseHandle(ol.hEvent);
|
||||||
|
|
||||||
|
if (!(_osfile(fd) & (FDEV | FPIPE))) {
|
||||||
|
LONG high = ol.OffsetHigh;
|
||||||
|
LONG low = ol.Offset + written;
|
||||||
|
if (low < ol.Offset)
|
||||||
|
++high;
|
||||||
|
SetFilePointer((HANDLE)_osfhnd(fd), low, &high, FILE_BEGIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
|
||||||
|
|
||||||
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Add table
Reference in a new issue