* sigproc.cc (remove_proc): Don't terminate the currently executing thread.
This commit is contained in:
parent
d1fc77322f
commit
480b13a37a
|
@ -1,3 +1,8 @@
|
||||||
|
2011-11-29 Christopher Faylor <me.cygwin2011@cgf.cx>
|
||||||
|
|
||||||
|
* sigproc.cc (remove_proc): Don't terminate the currently executing
|
||||||
|
thread.
|
||||||
|
|
||||||
2011-11-28 Christopher Faylor <me.cygwin2011@cgf.cx>
|
2011-11-28 Christopher Faylor <me.cygwin2011@cgf.cx>
|
||||||
|
|
||||||
* cygheap.cc (cygheap_fixup_in_child): Accommodate new HEAP_3*
|
* cygheap.cc (cygheap_fixup_in_child): Accommodate new HEAP_3*
|
||||||
|
|
|
@ -70,18 +70,22 @@ cygheap_fixup_in_child (bool execed)
|
||||||
{
|
{
|
||||||
cygheap->hooks.next = NULL;
|
cygheap->hooks.next = NULL;
|
||||||
cygheap->user_heap.base = NULL; /* We can allocate the heap anywhere */
|
cygheap->user_heap.base = NULL; /* We can allocate the heap anywhere */
|
||||||
/* Walk the allocated memory chain looking for orphaned memory from
|
}
|
||||||
previous execs */
|
/* Walk the allocated memory chain looking for orphaned memory from
|
||||||
for (_cmalloc_entry *rvc = cygheap->chain; rvc; rvc = rvc->prev)
|
previous execs or forks */
|
||||||
{
|
for (_cmalloc_entry *rvc = cygheap->chain; rvc; rvc = rvc->prev)
|
||||||
cygheap_entry *ce = (cygheap_entry *) rvc->data;
|
{
|
||||||
if (!rvc->ptr || rvc->b >= NBUCKETS || ce->type <= HEAP_1_START)
|
cygheap_entry *ce = (cygheap_entry *) rvc->data;
|
||||||
continue;
|
if (!rvc->ptr || rvc->b >= NBUCKETS || ce->type <= HEAP_1_START)
|
||||||
else if (ce->type < HEAP_1_MAX)
|
continue;
|
||||||
ce->type += HEAP_1_MAX; /* Mark for freeing after next exec */
|
else if (ce->type > HEAP_2_MAX)
|
||||||
else
|
_cfree (ce); /* Marked for freeing in any child */
|
||||||
_cfree (ce); /* Marked by parent for freeing in child */
|
else if (!execed)
|
||||||
}
|
continue;
|
||||||
|
else if (ce->type > HEAP_1_MAX)
|
||||||
|
_cfree (ce); /* Marked for freeing in execed child */
|
||||||
|
else
|
||||||
|
ce->type += HEAP_1_MAX; /* Mark for freeing after next exec */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,9 @@ enum cygheap_types
|
||||||
HEAP_1_MAX = 100,
|
HEAP_1_MAX = 100,
|
||||||
HEAP_2_STR,
|
HEAP_2_STR,
|
||||||
HEAP_2_DLL,
|
HEAP_2_DLL,
|
||||||
HEAP_MMAP = 200
|
HEAP_MMAP,
|
||||||
|
HEAP_2_MAX = 200,
|
||||||
|
HEAP_3_FHANDLER
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -28,6 +28,7 @@ details. */
|
||||||
#include "ntdll.h"
|
#include "ntdll.h"
|
||||||
#include "cygtls.h"
|
#include "cygtls.h"
|
||||||
#include "sigproc.h"
|
#include "sigproc.h"
|
||||||
|
#include "shared_info.h"
|
||||||
#include <asm/socket.h>
|
#include <asm/socket.h>
|
||||||
|
|
||||||
#define MAX_OVERLAPPED_WRITE_LEN (64 * 1024 * 1024)
|
#define MAX_OVERLAPPED_WRITE_LEN (64 * 1024 * 1024)
|
||||||
|
@ -37,6 +38,9 @@ static const int CHUNK_SIZE = 1024; /* Used for crlf conversions */
|
||||||
|
|
||||||
struct __cygwin_perfile *perfile_table;
|
struct __cygwin_perfile *perfile_table;
|
||||||
|
|
||||||
|
HANDLE NO_COPY fhandler_base_overlapped::asio_done;
|
||||||
|
LONG NO_COPY fhandler_base_overlapped::asio_close_counter;
|
||||||
|
|
||||||
void
|
void
|
||||||
fhandler_base::reset (const fhandler_base *from)
|
fhandler_base::reset (const fhandler_base *from)
|
||||||
{
|
{
|
||||||
|
@ -1152,17 +1156,77 @@ fhandler_base::close ()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI
|
||||||
|
flush_async_io (void *arg)
|
||||||
|
{
|
||||||
|
fhandler_base_overlapped *fh = (fhandler_base_overlapped *) arg;
|
||||||
|
debug_only_printf ("waiting for %s I/O for %s",
|
||||||
|
(fh->get_access () & GENERIC_WRITE) ? "write" : "read",
|
||||||
|
fh->get_name ());
|
||||||
|
SetEvent (fh->get_overlapped ()->hEvent); /* force has_ongoing_io to block */
|
||||||
|
bool res = fh->has_ongoing_io ();
|
||||||
|
debug_printf ("finished waiting for I/O from %s, res %d", fh->get_name (),
|
||||||
|
res);
|
||||||
|
fh->close ();
|
||||||
|
delete fh;
|
||||||
|
|
||||||
|
InterlockedDecrement (&fhandler_base_overlapped::asio_close_counter);
|
||||||
|
SetEvent (fhandler_base_overlapped::asio_done);
|
||||||
|
|
||||||
|
_my_tls._ctinfo->auto_release ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fhandler_base_overlapped::flush_all_async_io ()
|
||||||
|
{
|
||||||
|
while (asio_close_counter > 0)
|
||||||
|
if (WaitForSingleObject (asio_done, INFINITE) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
system_printf ("WaitForSingleObject failed, possible data loss in pipe, %E");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
asio_close_counter = 0;
|
||||||
|
if (asio_done)
|
||||||
|
CloseHandle (asio_done);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start a thread to handle closing of overlapped asynchronous I/O since
|
||||||
|
Windows amazingly does not seem to always flush I/O on close. */
|
||||||
|
void
|
||||||
|
fhandler_base_overlapped::check_later ()
|
||||||
|
{
|
||||||
|
set_close_on_exec (true);
|
||||||
|
char buf[MAX_PATH];
|
||||||
|
if (!asio_done
|
||||||
|
&& !(asio_done = CreateEvent (&sec_none_nih, false, false,
|
||||||
|
shared_name (buf, "asio",
|
||||||
|
GetCurrentProcessId ()))))
|
||||||
|
api_fatal ("CreateEvent failed, %E");
|
||||||
|
|
||||||
|
InterlockedIncrement (&asio_close_counter);
|
||||||
|
if (!new cygthread(flush_async_io, this, "flasio"))
|
||||||
|
api_fatal ("couldn't create a thread to track async I/O, %E");
|
||||||
|
debug_printf ("started thread to handle asynchronous closing for %s", get_name ());
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fhandler_base_overlapped::close ()
|
fhandler_base_overlapped::close ()
|
||||||
{
|
{
|
||||||
if (is_nonblocking () && io_pending)
|
int res;
|
||||||
|
/* Need to treat non-blocking I/O specially because Windows appears to
|
||||||
|
be brain-dead */
|
||||||
|
if (is_nonblocking () && has_ongoing_io ())
|
||||||
{
|
{
|
||||||
DWORD bytes;
|
clone (HEAP_3_FHANDLER)->check_later ();
|
||||||
wait_overlapped (1, !!(get_access () & GENERIC_WRITE), &bytes, false);
|
res = 0;
|
||||||
}
|
}
|
||||||
destroy_overlapped ();
|
else
|
||||||
return fhandler_base::close ();
|
{
|
||||||
|
destroy_overlapped ();
|
||||||
|
res = fhandler_base::close ();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1414,12 +1478,6 @@ fhandler_base::ptsname_r (char *, size_t)
|
||||||
return ENOTTY;
|
return ENOTTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
fhandler_base::operator delete (void *p)
|
|
||||||
{
|
|
||||||
cfree (p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Normal I/O constructor */
|
/* Normal I/O constructor */
|
||||||
fhandler_base::fhandler_base () :
|
fhandler_base::fhandler_base () :
|
||||||
status (),
|
status (),
|
||||||
|
@ -1836,13 +1894,10 @@ fhandler_base_overlapped::has_ongoing_io ()
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!IsEventSignalled (get_overlapped ()->hEvent))
|
if (!IsEventSignalled (get_overlapped ()->hEvent))
|
||||||
{
|
return true;
|
||||||
set_errno (EAGAIN);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
io_pending = false;
|
io_pending = false;
|
||||||
DWORD nbytes;
|
DWORD nbytes;
|
||||||
GetOverlappedResult (get_output_handle (), get_overlapped (), &nbytes, 0);
|
GetOverlappedResult (get_output_handle (), get_overlapped (), &nbytes, true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1930,7 +1985,7 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug_printf ("res %u, err %u", (unsigned) res, err);
|
debug_printf ("res %u, Win32 Error %u", (unsigned) res, err);
|
||||||
*bytes = (DWORD) -1;
|
*bytes = (DWORD) -1;
|
||||||
__seterrno_from_win_error (err);
|
__seterrno_from_win_error (err);
|
||||||
if (writing && err == ERROR_NO_DATA)
|
if (writing && err == ERROR_NO_DATA)
|
||||||
|
@ -1970,7 +2025,10 @@ fhandler_base_overlapped::raw_write (const void *ptr, size_t len)
|
||||||
{
|
{
|
||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
if (has_ongoing_io ())
|
if (has_ongoing_io ())
|
||||||
nbytes = (DWORD) -1;
|
{
|
||||||
|
set_errno (EAGAIN);
|
||||||
|
nbytes = (DWORD) -1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t chunk;
|
size_t chunk;
|
||||||
|
|
|
@ -409,7 +409,7 @@ public:
|
||||||
raixput = raixget = ralen = rabuflen = 0;
|
raixput = raixget = ralen = rabuflen = 0;
|
||||||
rabuf = NULL;
|
rabuf = NULL;
|
||||||
}
|
}
|
||||||
void operator delete (void *);
|
void operator delete (void *p) {cfree (p);}
|
||||||
virtual void set_eof () {}
|
virtual void set_eof () {}
|
||||||
virtual int mkdir (mode_t mode);
|
virtual int mkdir (mode_t mode);
|
||||||
virtual int rmdir ();
|
virtual int rmdir ();
|
||||||
|
@ -435,9 +435,9 @@ public:
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual fhandler_base *clone ()
|
virtual fhandler_base *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_base));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_base));
|
||||||
fhandler_base *fh = new (ptr) fhandler_base (ptr);
|
fhandler_base *fh = new (ptr) fhandler_base (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -602,9 +602,9 @@ class fhandler_socket: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_socket *clone ()
|
fhandler_socket *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_socket));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_socket));
|
||||||
fhandler_socket *fh = new (ptr) fhandler_socket (ptr);
|
fhandler_socket *fh = new (ptr) fhandler_socket (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -613,6 +613,8 @@ class fhandler_socket: public fhandler_base
|
||||||
|
|
||||||
class fhandler_base_overlapped: public fhandler_base
|
class fhandler_base_overlapped: public fhandler_base
|
||||||
{
|
{
|
||||||
|
static HANDLE asio_done;
|
||||||
|
static LONG asio_close_counter;
|
||||||
protected:
|
protected:
|
||||||
enum wait_return
|
enum wait_return
|
||||||
{
|
{
|
||||||
|
@ -647,6 +649,9 @@ public:
|
||||||
int close ();
|
int close ();
|
||||||
int dup (fhandler_base *child, int);
|
int dup (fhandler_base *child, int);
|
||||||
|
|
||||||
|
void check_later ();
|
||||||
|
static void flush_all_async_io () __attribute__ ((regparm (1)));;
|
||||||
|
|
||||||
fhandler_base_overlapped (void *) {}
|
fhandler_base_overlapped (void *) {}
|
||||||
|
|
||||||
virtual void copyto (fhandler_base *x)
|
virtual void copyto (fhandler_base *x)
|
||||||
|
@ -656,13 +661,15 @@ public:
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual fhandler_base_overlapped *clone ()
|
virtual fhandler_base_overlapped *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_base_overlapped));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_base_overlapped));
|
||||||
fhandler_base_overlapped *fh = new (ptr) fhandler_base_overlapped (ptr);
|
fhandler_base_overlapped *fh = new (ptr) fhandler_base_overlapped (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend DWORD WINAPI flush_async_io (void *);
|
||||||
};
|
};
|
||||||
|
|
||||||
class fhandler_pipe: public fhandler_base_overlapped
|
class fhandler_pipe: public fhandler_base_overlapped
|
||||||
|
@ -701,9 +708,9 @@ public:
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_pipe *clone ()
|
fhandler_pipe *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pipe));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_pipe));
|
||||||
fhandler_pipe *fh = new (ptr) fhandler_pipe (ptr);
|
fhandler_pipe *fh = new (ptr) fhandler_pipe (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -739,9 +746,9 @@ public:
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_fifo *clone ()
|
fhandler_fifo *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_fifo));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_fifo));
|
||||||
fhandler_fifo *fh = new (ptr) fhandler_fifo (ptr);
|
fhandler_fifo *fh = new (ptr) fhandler_fifo (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -768,9 +775,9 @@ class fhandler_mailslot : public fhandler_base_overlapped
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_mailslot *clone ()
|
fhandler_mailslot *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_mailslot));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_mailslot));
|
||||||
fhandler_mailslot *fh = new (ptr) fhandler_mailslot (ptr);
|
fhandler_mailslot *fh = new (ptr) fhandler_mailslot (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -817,9 +824,9 @@ class fhandler_dev_raw: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_dev_raw *clone ()
|
fhandler_dev_raw *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_raw));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev_raw));
|
||||||
fhandler_dev_raw *fh = new (ptr) fhandler_dev_raw (ptr);
|
fhandler_dev_raw *fh = new (ptr) fhandler_dev_raw (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -877,9 +884,9 @@ class fhandler_dev_floppy: public fhandler_dev_raw
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_dev_floppy *clone ()
|
fhandler_dev_floppy *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_floppy));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev_floppy));
|
||||||
fhandler_dev_floppy *fh = new (ptr) fhandler_dev_floppy (ptr);
|
fhandler_dev_floppy *fh = new (ptr) fhandler_dev_floppy (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -925,9 +932,9 @@ class fhandler_dev_tape: public fhandler_dev_raw
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_dev_tape *clone ()
|
fhandler_dev_tape *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_tape));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev_tape));
|
||||||
fhandler_dev_tape *fh = new (ptr) fhandler_dev_tape (ptr);
|
fhandler_dev_tape *fh = new (ptr) fhandler_dev_tape (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -991,9 +998,9 @@ class fhandler_disk_file: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_disk_file *clone ()
|
fhandler_disk_file *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_disk_file));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_disk_file));
|
||||||
fhandler_disk_file *fh = new (ptr) fhandler_disk_file (ptr);
|
fhandler_disk_file *fh = new (ptr) fhandler_disk_file (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1029,9 +1036,9 @@ class fhandler_cygdrive: public fhandler_disk_file
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_cygdrive *clone ()
|
fhandler_cygdrive *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_cygdrive));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_cygdrive));
|
||||||
fhandler_cygdrive *fh = new (ptr) fhandler_cygdrive (ptr);
|
fhandler_cygdrive *fh = new (ptr) fhandler_cygdrive (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1093,9 +1100,9 @@ class fhandler_serial: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_serial *clone ()
|
fhandler_serial *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_serial));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_serial));
|
||||||
fhandler_serial *fh = new (ptr) fhandler_serial (ptr);
|
fhandler_serial *fh = new (ptr) fhandler_serial (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1151,9 +1158,9 @@ class fhandler_termios: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual fhandler_termios *clone ()
|
virtual fhandler_termios *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_termios));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_termios));
|
||||||
fhandler_termios *fh = new (ptr) fhandler_termios (ptr);
|
fhandler_termios *fh = new (ptr) fhandler_termios (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1350,9 +1357,9 @@ private:
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_console *clone ()
|
fhandler_console *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_console));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_console));
|
||||||
fhandler_console *fh = new (ptr) fhandler_console (ptr);
|
fhandler_console *fh = new (ptr) fhandler_console (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1394,9 +1401,9 @@ class fhandler_pty_common: public fhandler_termios
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual fhandler_pty_common *clone ()
|
virtual fhandler_pty_common *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pty_common));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_pty_common));
|
||||||
fhandler_pty_common *fh = new (ptr) fhandler_pty_common (ptr);
|
fhandler_pty_common *fh = new (ptr) fhandler_pty_common (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1448,9 +1455,9 @@ class fhandler_pty_slave: public fhandler_pty_common
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_pty_slave *clone ()
|
fhandler_pty_slave *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pty_slave));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_pty_slave));
|
||||||
fhandler_pty_slave *fh = new (ptr) fhandler_pty_slave (ptr);
|
fhandler_pty_slave *fh = new (ptr) fhandler_pty_slave (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1507,9 +1514,9 @@ public:
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_pty_master *clone ()
|
fhandler_pty_master *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pty_master));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_pty_master));
|
||||||
fhandler_pty_master *fh = new (ptr) fhandler_pty_master (ptr);
|
fhandler_pty_master *fh = new (ptr) fhandler_pty_master (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1534,9 +1541,9 @@ class fhandler_dev_null: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_dev_null *clone ()
|
fhandler_dev_null *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_null));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev_null));
|
||||||
fhandler_dev_null *fh = new (ptr) fhandler_dev_null (ptr);
|
fhandler_dev_null *fh = new (ptr) fhandler_dev_null (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1569,9 +1576,9 @@ class fhandler_dev_zero: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_dev_zero *clone ()
|
fhandler_dev_zero *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_zero));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev_zero));
|
||||||
fhandler_dev_zero *fh = new (ptr) fhandler_dev_zero (ptr);
|
fhandler_dev_zero *fh = new (ptr) fhandler_dev_zero (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1607,9 +1614,9 @@ class fhandler_dev_random: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_dev_random *clone ()
|
fhandler_dev_random *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_random));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev_random));
|
||||||
fhandler_dev_random *fh = new (ptr) fhandler_dev_random (ptr);
|
fhandler_dev_random *fh = new (ptr) fhandler_dev_random (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1647,9 +1654,9 @@ class fhandler_dev_mem: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_dev_mem *clone ()
|
fhandler_dev_mem *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_mem));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev_mem));
|
||||||
fhandler_dev_mem *fh = new (ptr) fhandler_dev_mem (ptr);
|
fhandler_dev_mem *fh = new (ptr) fhandler_dev_mem (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1683,9 +1690,9 @@ class fhandler_dev_clipboard: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_dev_clipboard *clone ()
|
fhandler_dev_clipboard *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_clipboard));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev_clipboard));
|
||||||
fhandler_dev_clipboard *fh = new (ptr) fhandler_dev_clipboard (ptr);
|
fhandler_dev_clipboard *fh = new (ptr) fhandler_dev_clipboard (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1722,9 +1729,9 @@ class fhandler_windows: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_windows *clone ()
|
fhandler_windows *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_windows));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_windows));
|
||||||
fhandler_windows *fh = new (ptr) fhandler_windows (ptr);
|
fhandler_windows *fh = new (ptr) fhandler_windows (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1769,9 +1776,9 @@ class fhandler_dev_dsp: public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_dev_dsp *clone ()
|
fhandler_dev_dsp *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_dsp));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev_dsp));
|
||||||
fhandler_dev_dsp *fh = new (ptr) fhandler_dev_dsp (ptr);
|
fhandler_dev_dsp *fh = new (ptr) fhandler_dev_dsp (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1820,9 +1827,9 @@ class fhandler_virtual : public fhandler_base
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual fhandler_virtual *clone ()
|
virtual fhandler_virtual *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_virtual));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_virtual));
|
||||||
fhandler_virtual *fh = new (ptr) fhandler_virtual (ptr);
|
fhandler_virtual *fh = new (ptr) fhandler_virtual (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1852,9 +1859,9 @@ class fhandler_proc: public fhandler_virtual
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual fhandler_proc *clone ()
|
virtual fhandler_proc *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_proc));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_proc));
|
||||||
fhandler_proc *fh = new (ptr) fhandler_proc (ptr);
|
fhandler_proc *fh = new (ptr) fhandler_proc (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1888,9 +1895,9 @@ class fhandler_procsys: public fhandler_virtual
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_procsys *clone ()
|
fhandler_procsys *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_procsys));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_procsys));
|
||||||
fhandler_procsys *fh = new (ptr) fhandler_procsys (ptr);
|
fhandler_procsys *fh = new (ptr) fhandler_procsys (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1917,9 +1924,9 @@ class fhandler_procsysvipc: public fhandler_proc
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_procsysvipc *clone ()
|
fhandler_procsysvipc *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_procsysvipc));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_procsysvipc));
|
||||||
fhandler_procsysvipc *fh = new (ptr) fhandler_procsysvipc (ptr);
|
fhandler_procsysvipc *fh = new (ptr) fhandler_procsysvipc (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1947,9 +1954,9 @@ class fhandler_netdrive: public fhandler_virtual
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_netdrive *clone ()
|
fhandler_netdrive *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_netdrive));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_netdrive));
|
||||||
fhandler_netdrive *fh = new (ptr) fhandler_netdrive (ptr);
|
fhandler_netdrive *fh = new (ptr) fhandler_netdrive (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -1987,9 +1994,9 @@ class fhandler_registry: public fhandler_proc
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_registry *clone ()
|
fhandler_registry *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_registry));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_registry));
|
||||||
fhandler_registry *fh = new (ptr) fhandler_registry (ptr);
|
fhandler_registry *fh = new (ptr) fhandler_registry (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -2019,9 +2026,9 @@ class fhandler_process: public fhandler_proc
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_process *clone ()
|
fhandler_process *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_process));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_process));
|
||||||
fhandler_process *fh = new (ptr) fhandler_process (ptr);
|
fhandler_process *fh = new (ptr) fhandler_process (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
@ -2048,9 +2055,9 @@ class fhandler_procnet: public fhandler_proc
|
||||||
x->reset (this);
|
x->reset (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_procnet *clone ()
|
fhandler_procnet *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_procnet));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_procnet));
|
||||||
fhandler_procnet *fh = new (ptr) fhandler_procnet (ptr);
|
fhandler_procnet *fh = new (ptr) fhandler_procnet (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
|
|
|
@ -484,48 +484,51 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, bool writing)
|
||||||
FILE_PIPE_LOCAL_INFORMATION fpli = {0};
|
FILE_PIPE_LOCAL_INFORMATION fpli = {0};
|
||||||
|
|
||||||
bool res = false;
|
bool res = false;
|
||||||
if (NtQueryInformationFile (h,
|
if (!fh->has_ongoing_io ())
|
||||||
&iosb,
|
|
||||||
&fpli,
|
|
||||||
sizeof (fpli),
|
|
||||||
FilePipeLocalInformation))
|
|
||||||
{
|
{
|
||||||
/* If NtQueryInformationFile fails, optimistically assume the
|
if (NtQueryInformationFile (h,
|
||||||
pipe is writable. This could happen if we somehow
|
&iosb,
|
||||||
inherit a pipe that doesn't permit FILE_READ_ATTRIBUTES
|
&fpli,
|
||||||
access on the write end. */
|
sizeof (fpli),
|
||||||
select_printf ("fd %d, %s, NtQueryInformationFile failed",
|
FilePipeLocalInformation))
|
||||||
fd, fh->get_name ());
|
|
||||||
res = writing ? true : -1;
|
|
||||||
}
|
|
||||||
else if (!writing)
|
|
||||||
{
|
|
||||||
res = !!fpli.ReadDataAvailable;
|
|
||||||
paranoid_printf ("fd %d, %s, read avail %u", fd, fh->get_name (), fpli.ReadDataAvailable);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If there is anything available in the pipe buffer then signal
|
|
||||||
that. This means that a pipe could still block since you could
|
|
||||||
be trying to write more to the pipe than is available in the
|
|
||||||
buffer but that is the hazard of select(). */
|
|
||||||
if ((fpli.WriteQuotaAvailable = (fpli.OutboundQuota - fpli.ReadDataAvailable)))
|
|
||||||
{
|
{
|
||||||
paranoid_printf ("fd %d, %s, write: size %lu, avail %lu", fd,
|
/* If NtQueryInformationFile fails, optimistically assume the
|
||||||
fh->get_name (), fpli.OutboundQuota,
|
pipe is writable. This could happen if we somehow
|
||||||
fpli.WriteQuotaAvailable);
|
inherit a pipe that doesn't permit FILE_READ_ATTRIBUTES
|
||||||
res = true;
|
access on the write end. */
|
||||||
|
select_printf ("fd %d, %s, NtQueryInformationFile failed",
|
||||||
|
fd, fh->get_name ());
|
||||||
|
res = writing ? true : -1;
|
||||||
}
|
}
|
||||||
/* If we somehow inherit a tiny pipe (size < PIPE_BUF), then consider
|
else if (!writing)
|
||||||
the pipe writable only if it is completely empty, to minimize the
|
|
||||||
probability that a subsequent write will block. */
|
|
||||||
else if (fpli.OutboundQuota < PIPE_BUF &&
|
|
||||||
fpli.WriteQuotaAvailable == fpli.OutboundQuota)
|
|
||||||
{
|
{
|
||||||
select_printf ("fd, %s, write tiny pipe: size %lu, avail %lu",
|
res = !!fpli.ReadDataAvailable;
|
||||||
fd, fh->get_name (), fpli.OutboundQuota,
|
paranoid_printf ("fd %d, %s, read avail %u", fd, fh->get_name (), fpli.ReadDataAvailable);
|
||||||
fpli.WriteQuotaAvailable);
|
}
|
||||||
res = true;
|
else
|
||||||
|
{
|
||||||
|
/* If there is anything available in the pipe buffer then signal
|
||||||
|
that. This means that a pipe could still block since you could
|
||||||
|
be trying to write more to the pipe than is available in the
|
||||||
|
buffer but that is the hazard of select(). */
|
||||||
|
if ((fpli.WriteQuotaAvailable = (fpli.OutboundQuota - fpli.ReadDataAvailable)))
|
||||||
|
{
|
||||||
|
paranoid_printf ("fd %d, %s, write: size %lu, avail %lu", fd,
|
||||||
|
fh->get_name (), fpli.OutboundQuota,
|
||||||
|
fpli.WriteQuotaAvailable);
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
/* If we somehow inherit a tiny pipe (size < PIPE_BUF), then consider
|
||||||
|
the pipe writable only if it is completely empty, to minimize the
|
||||||
|
probability that a subsequent write will block. */
|
||||||
|
else if (fpli.OutboundQuota < PIPE_BUF &&
|
||||||
|
fpli.WriteQuotaAvailable == fpli.OutboundQuota)
|
||||||
|
{
|
||||||
|
select_printf ("fd, %s, write tiny pipe: size %lu, avail %lu",
|
||||||
|
fd, fh->get_name (), fpli.OutboundQuota,
|
||||||
|
fpli.WriteQuotaAvailable);
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res ?: -!!(fpli.NamedPipeState & FILE_PIPE_CLOSING_STATE);
|
return res ?: -!!(fpli.NamedPipeState & FILE_PIPE_CLOSING_STATE);
|
||||||
|
|
|
@ -1135,7 +1135,10 @@ static bool __stdcall
|
||||||
remove_proc (int ci)
|
remove_proc (int ci)
|
||||||
{
|
{
|
||||||
if (have_execed)
|
if (have_execed)
|
||||||
procs[ci].wait_thread->terminate_thread ();
|
{
|
||||||
|
if (_my_tls._ctinfo != procs[ci].wait_thread)
|
||||||
|
procs[ci].wait_thread->terminate_thread ();
|
||||||
|
}
|
||||||
else if (procs[ci]->exists ())
|
else if (procs[ci]->exists ())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,7 @@ close_all_files (bool norelease)
|
||||||
if (!have_execed && cygheap->ctty)
|
if (!have_execed && cygheap->ctty)
|
||||||
cygheap->close_ctty ();
|
cygheap->close_ctty ();
|
||||||
|
|
||||||
|
fhandler_base_overlapped::flush_all_async_io ();
|
||||||
if (h)
|
if (h)
|
||||||
SetStdHandle (STD_ERROR_HANDLE, h);
|
SetStdHandle (STD_ERROR_HANDLE, h);
|
||||||
cygheap->fdtab.unlock ();
|
cygheap->fdtab.unlock ();
|
||||||
|
|
|
@ -15,7 +15,7 @@ details. */
|
||||||
#define INP_BUFFER_SIZE 256
|
#define INP_BUFFER_SIZE 256
|
||||||
#define OUT_BUFFER_SIZE 256
|
#define OUT_BUFFER_SIZE 256
|
||||||
#define NTTYS 64
|
#define NTTYS 64
|
||||||
#define real_tty_attached(p) ((p)->ctty >= 0 && !iscons_dev ((p)->ctty))
|
#define real_tty_attached(p) ((p)->ctty > 0 && !iscons_dev ((p)->ctty))
|
||||||
|
|
||||||
/* Input/Output/ioctl events */
|
/* Input/Output/ioctl events */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue