try to fix problems force-closing stuck ports under Windows
svn: r12056
This commit is contained in:
parent
1d1aea5b2b
commit
69685db892
|
@ -122,11 +122,14 @@ typedef struct Win_FD_Input_Thread {
|
|||
/* This is malloced for use in a Win32 thread */
|
||||
HANDLE fd;
|
||||
volatile int avail, err, checking;
|
||||
int *refcount;
|
||||
HANDLE eof;
|
||||
unsigned char *buffer;
|
||||
HANDLE checking_sema, ready_sema, you_clean_up_sema;
|
||||
} Win_FD_Input_Thread;
|
||||
|
||||
static HANDLE refcount_sema;
|
||||
|
||||
typedef struct Win_FD_Output_Thread {
|
||||
/* This is malloced for use in a Win32 thread */
|
||||
HANDLE fd;
|
||||
|
@ -144,6 +147,7 @@ typedef struct Win_FD_Output_Thread {
|
|||
volatile int done, err_no;
|
||||
volatile unsigned int buflen, bufstart, bufend; /* used for blocking, only */
|
||||
unsigned char *buffer; /* used for blocking, only */
|
||||
int *refcount;
|
||||
HANDLE lock_sema, work_sema, ready_sema, you_clean_up_sema;
|
||||
/* lock_sema protects the fields, work_sema starts the flush or
|
||||
flush-checking thread to work, ready_sema indicates that a flush
|
||||
|
@ -4532,6 +4536,26 @@ scheme_make_file_input_port(FILE *fp)
|
|||
# ifdef WINDOWS_FILE_HANDLES
|
||||
static long WindowsFDReader(Win_FD_Input_Thread *th);
|
||||
static void WindowsFDICleanup(Win_FD_Input_Thread *th);
|
||||
typedef BOOL (WINAPI* CSI_proc)(HANDLE);
|
||||
|
||||
static CSI_proc get_csi(void)
|
||||
{
|
||||
static int tried_csi = 0;
|
||||
static CSI_proc csi;
|
||||
|
||||
START_XFORM_SKIP;
|
||||
if (!tried_csi) {
|
||||
HMODULE hm;
|
||||
hm = LoadLibrary("kernel32.dll");
|
||||
if (hm)
|
||||
csi = (CSI_proc)GetProcAddress(hm, "CancelSynchronousIo");
|
||||
else
|
||||
csi = NULL;
|
||||
tried_csi = 1;
|
||||
}
|
||||
END_XFORM_SKIP;
|
||||
return csi;
|
||||
}
|
||||
# endif
|
||||
|
||||
/* forward decl: */
|
||||
|
@ -4914,11 +4938,10 @@ fd_close_input(Scheme_Input_Port *port)
|
|||
|
||||
fip = (Scheme_FD *)port->port_data;
|
||||
|
||||
if (fip->refcount)
|
||||
*fip->refcount -= 1;
|
||||
|
||||
#ifdef WINDOWS_FILE_HANDLES
|
||||
if (fip->th) {
|
||||
CSI_proc csi;
|
||||
|
||||
/* -1 for checking means "shut down" */
|
||||
fip->th->checking = -1;
|
||||
ReleaseSemaphore(fip->th->checking_sema, 1, NULL);
|
||||
|
@ -4928,18 +4951,29 @@ fd_close_input(Scheme_Input_Port *port)
|
|||
fip->th->eof = NULL;
|
||||
}
|
||||
|
||||
csi = get_csi();
|
||||
if (csi) {
|
||||
csi(fip->th->thread);
|
||||
/* See note on csi at fd_close_output */
|
||||
}
|
||||
|
||||
/* Try to get out of cleaning up the records (since they can't be
|
||||
cleaned until the thread is also done: */
|
||||
if (WaitForSingleObject(fip->th->you_clean_up_sema, 0) != WAIT_OBJECT_0) {
|
||||
/* The other thread exited and left us with clean-up: */
|
||||
WindowsFDICleanup(fip->th);
|
||||
} /* otherwise, thread is responsible for clean-up */
|
||||
}
|
||||
if (!fip->refcount || !*fip->refcount) {
|
||||
CloseHandle((HANDLE)fip->fd);
|
||||
--scheme_file_open_count;
|
||||
} else {
|
||||
if (fip->refcount)
|
||||
*fip->refcount -= 1;
|
||||
if (!fip->refcount || !*fip->refcount) {
|
||||
CloseHandle((HANDLE)fip->fd);
|
||||
--scheme_file_open_count;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (fip->refcount)
|
||||
*fip->refcount -= 1;
|
||||
if (!fip->refcount || !*fip->refcount) {
|
||||
int cr;
|
||||
do {
|
||||
|
@ -5088,6 +5122,11 @@ make_fd_input_port(int fd, Scheme_Object *name, int regfile, int win_textmode, i
|
|||
th->ready_sema = sm;
|
||||
sm = CreateSemaphore(NULL, 1, 1, NULL);
|
||||
th->you_clean_up_sema = sm;
|
||||
if (refcount) {
|
||||
th->refcount = refcount;
|
||||
if (!refcount_sema)
|
||||
refcount_sema = CreateSemaphore(NULL, 1, 1, NULL);
|
||||
}
|
||||
|
||||
h = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)WindowsFDReader, th, 0, &id);
|
||||
|
||||
|
@ -5161,9 +5200,21 @@ static long WindowsFDReader(Win_FD_Input_Thread *th)
|
|||
|
||||
static void WindowsFDICleanup(Win_FD_Input_Thread *th)
|
||||
{
|
||||
int rc;
|
||||
|
||||
CloseHandle(th->checking_sema);
|
||||
CloseHandle(th->ready_sema);
|
||||
CloseHandle(th->you_clean_up_sema);
|
||||
|
||||
if (th->refcount) {
|
||||
WaitForSingleObject(refcount_sema, INFINITE);
|
||||
*th->refcount -= 1;
|
||||
rc = *th->refcount;
|
||||
ReleaseSemaphore(refcount_sema, 1, NULL);
|
||||
} else
|
||||
rc = 0;
|
||||
if (!rc) CloseHandle(th->fd);
|
||||
|
||||
free(th->buffer);
|
||||
free(th);
|
||||
}
|
||||
|
@ -5906,6 +5957,11 @@ static long flush_fd(Scheme_Output_Port *op,
|
|||
oth->ready_sema = sm;
|
||||
sm = CreateSemaphore(NULL, 1, 1, NULL);
|
||||
oth->you_clean_up_sema = sm;
|
||||
if (refcount) {
|
||||
oth->refcount = refcount;
|
||||
if (!refcount_sema)
|
||||
refcount_sema = CreateSemaphore(NULL, 1, 1, NULL);
|
||||
}
|
||||
|
||||
h = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)WindowsFDWriter, oth, 0, &id);
|
||||
|
||||
|
@ -6134,10 +6190,6 @@ fd_write_string(Scheme_Output_Port *port,
|
|||
return len;
|
||||
}
|
||||
|
||||
#ifdef WINDOWS_FILE_HANDLES
|
||||
typedef BOOL (WINAPI* CSI_proc)(HANDLE);
|
||||
#endif
|
||||
|
||||
static void
|
||||
fd_close_output(Scheme_Output_Port *port)
|
||||
{
|
||||
|
@ -6163,25 +6215,11 @@ fd_close_output(Scheme_Output_Port *port)
|
|||
if (port->closed)
|
||||
return;
|
||||
|
||||
if (fop->refcount)
|
||||
*fop->refcount -= 1;
|
||||
|
||||
#ifdef WINDOWS_FILE_HANDLES
|
||||
if (fop->oth) {
|
||||
static int tried_csi = 0;
|
||||
static CSI_proc csi;
|
||||
CSI_proc csi;
|
||||
|
||||
START_XFORM_SKIP;
|
||||
if (!tried_csi) {
|
||||
HMODULE hm;
|
||||
hm = LoadLibrary("kernel32.dll");
|
||||
if (hm)
|
||||
csi = (BOOL (WINAPI*)(HANDLE))GetProcAddress(hm, "CancelSynchronousIo");
|
||||
else
|
||||
csi = NULL;
|
||||
tried_csi = 1;
|
||||
}
|
||||
END_XFORM_SKIP;
|
||||
csi = get_csi();
|
||||
|
||||
if (csi) {
|
||||
csi(fop->oth->thread);
|
||||
|
@ -6200,12 +6238,18 @@ fd_close_output(Scheme_Output_Port *port)
|
|||
WindowsFDOCleanup(fop->oth);
|
||||
} /* otherwise, thread is responsible for clean-up */
|
||||
fop->oth = NULL;
|
||||
}
|
||||
if (!fop->refcount || !*fop->refcount) {
|
||||
CloseHandle((HANDLE)fop->fd);
|
||||
--scheme_file_open_count;
|
||||
} else {
|
||||
if (fop->refcount)
|
||||
*fop->refcount -= 1;
|
||||
if (!fop->refcount || !*fop->refcount) {
|
||||
CloseHandle((HANDLE)fop->fd);
|
||||
--scheme_file_open_count;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (fop->refcount)
|
||||
*fop->refcount -= 1;
|
||||
|
||||
if (!fop->refcount || !*fop->refcount) {
|
||||
int cr;
|
||||
do {
|
||||
|
@ -6382,9 +6426,21 @@ static long WindowsFDWriter(Win_FD_Output_Thread *oth)
|
|||
|
||||
static void WindowsFDOCleanup(Win_FD_Output_Thread *oth)
|
||||
{
|
||||
int rc;
|
||||
|
||||
CloseHandle(oth->lock_sema);
|
||||
CloseHandle(oth->work_sema);
|
||||
CloseHandle(oth->you_clean_up_sema);
|
||||
|
||||
if (oth->refcount) {
|
||||
WaitForSingleObject(refcount_sema, INFINITE);
|
||||
*oth->refcount -= 1;
|
||||
rc = *oth->refcount;
|
||||
ReleaseSemaphore(refcount_sema, 1, NULL);
|
||||
} else
|
||||
rc = 0;
|
||||
if (!rc) CloseHandle(oth->fd);
|
||||
|
||||
if (oth->buffer)
|
||||
free(oth->buffer);
|
||||
free(oth);
|
||||
|
|
Loading…
Reference in New Issue
Block a user