w32: Merge all the object tables of w32-io into one.
* src/w32-io.c (fd_table_size): New. Used in most places instead of the MAX_SLAFD constant. (reader_table, writer_table, notify_table): Merge them into ... (fd_table): this table. Chnage all affected code to take just one lock. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
79fc7c0fe8
commit
338e9edfdb
505
src/w32-io.c
505
src/w32-io.c
@ -43,9 +43,69 @@
|
||||
#include "sys-util.h"
|
||||
|
||||
|
||||
/* FIXME: Optimize. */
|
||||
/* The number of entries in our file table. We may eventually use a
|
||||
* lower value and dynamically resize the table. */
|
||||
#define MAX_SLAFD 512
|
||||
|
||||
#define handle_to_fd(a) ((int)(a))
|
||||
|
||||
#define READBUF_SIZE 4096
|
||||
#define WRITEBUF_SIZE 4096
|
||||
#define PIPEBUF_SIZE 4096
|
||||
|
||||
|
||||
/* The context used by a reader thread. */
|
||||
struct reader_context_s
|
||||
{
|
||||
HANDLE file_hd;
|
||||
int file_sock;
|
||||
HANDLE thread_hd;
|
||||
int refcount; /* Bumbed if the FD has been duped and thus we have
|
||||
* another FD referencinf this context. */
|
||||
|
||||
DECLARE_LOCK (mutex);
|
||||
|
||||
int stop_me;
|
||||
int eof;
|
||||
int eof_shortcut;
|
||||
int error;
|
||||
int error_code;
|
||||
|
||||
/* This is manually reset. */
|
||||
HANDLE have_data_ev;
|
||||
/* This is automatically reset. */
|
||||
HANDLE have_space_ev;
|
||||
/* This is manually reset but actually only triggered once. */
|
||||
HANDLE close_ev;
|
||||
|
||||
size_t readpos, writepos;
|
||||
char buffer[READBUF_SIZE];
|
||||
};
|
||||
|
||||
|
||||
/* The context used by a writer thread. */
|
||||
struct writer_context_s
|
||||
{
|
||||
HANDLE file_hd;
|
||||
int file_sock;
|
||||
HANDLE thread_hd;
|
||||
int refcount;
|
||||
|
||||
DECLARE_LOCK (mutex);
|
||||
|
||||
int stop_me;
|
||||
int error;
|
||||
int error_code;
|
||||
|
||||
/* This is manually reset. */
|
||||
HANDLE have_data;
|
||||
HANDLE is_empty;
|
||||
HANDLE close_ev;
|
||||
size_t nbytes;
|
||||
char buffer[WRITEBUF_SIZE];
|
||||
};
|
||||
|
||||
|
||||
/* An object to keep track of HANDLEs and sockets and map them to an
|
||||
* integer similar to what we use in Unix. Note that despite this
|
||||
* integer is often named "fd", it is not a file descriptor but really
|
||||
@ -75,7 +135,23 @@ static struct
|
||||
want to close something. Using the same handle for these
|
||||
duplicates works just fine. */
|
||||
int dup_from;
|
||||
|
||||
/* The context of an associated reader object or NULL. */
|
||||
struct reader_context_s *reader;
|
||||
|
||||
/* The context of an associated writer object or NULL. */
|
||||
struct writer_context_s *writer;
|
||||
|
||||
/* A notification hanlder. Noet that we current support only one
|
||||
* callback per fd. */
|
||||
struct {
|
||||
_gpgme_close_notify_handler_t handler;
|
||||
void *value;
|
||||
} notify;
|
||||
|
||||
} fd_table[MAX_SLAFD];
|
||||
static size_t fd_table_size = MAX_SLAFD;
|
||||
|
||||
DEFINE_STATIC_LOCK (fd_table_lock);
|
||||
|
||||
|
||||
@ -89,11 +165,11 @@ new_fd (void)
|
||||
|
||||
LOCK (fd_table_lock);
|
||||
|
||||
for (idx = 0; idx < MAX_SLAFD; idx++)
|
||||
for (idx = 0; idx < fd_table_size; idx++)
|
||||
if (! fd_table[idx].used)
|
||||
break;
|
||||
|
||||
if (idx == MAX_SLAFD)
|
||||
if (idx == fd_table_size)
|
||||
{
|
||||
gpg_err_set_errno (EIO);
|
||||
idx = -1;
|
||||
@ -104,6 +180,8 @@ new_fd (void)
|
||||
fd_table[idx].handle = INVALID_HANDLE_VALUE;
|
||||
fd_table[idx].socket = INVALID_SOCKET;
|
||||
fd_table[idx].dup_from = -1;
|
||||
fd_table[idx].notify.handler = NULL;
|
||||
fd_table[idx].notify.value = NULL;
|
||||
}
|
||||
|
||||
UNLOCK (fd_table_lock);
|
||||
@ -117,7 +195,7 @@ new_fd (void)
|
||||
void
|
||||
release_fd (int fd)
|
||||
{
|
||||
if (fd < 0 || fd >= MAX_SLAFD)
|
||||
if (fd < 0 || fd >= fd_table_size)
|
||||
return;
|
||||
|
||||
LOCK (fd_table_lock);
|
||||
@ -128,99 +206,14 @@ release_fd (int fd)
|
||||
fd_table[fd].handle = INVALID_HANDLE_VALUE;
|
||||
fd_table[fd].socket = INVALID_SOCKET;
|
||||
fd_table[fd].dup_from = -1;
|
||||
fd_table[fd].notify.handler = NULL;
|
||||
fd_table[fd].notify.value = NULL;
|
||||
}
|
||||
|
||||
UNLOCK (fd_table_lock);
|
||||
}
|
||||
|
||||
|
||||
#define handle_to_fd(a) ((int)(a))
|
||||
|
||||
#define READBUF_SIZE 4096
|
||||
#define WRITEBUF_SIZE 4096
|
||||
#define PIPEBUF_SIZE 4096
|
||||
#define MAX_READERS 64
|
||||
#define MAX_WRITERS 64
|
||||
|
||||
static struct
|
||||
{
|
||||
int inuse;
|
||||
int fd;
|
||||
_gpgme_close_notify_handler_t handler;
|
||||
void *value;
|
||||
} notify_table[MAX_SLAFD];
|
||||
DEFINE_STATIC_LOCK (notify_table_lock);
|
||||
|
||||
|
||||
struct reader_context_s
|
||||
{
|
||||
HANDLE file_hd;
|
||||
int file_sock;
|
||||
HANDLE thread_hd;
|
||||
int refcount;
|
||||
|
||||
DECLARE_LOCK (mutex);
|
||||
|
||||
int stop_me;
|
||||
int eof;
|
||||
int eof_shortcut;
|
||||
int error;
|
||||
int error_code;
|
||||
|
||||
/* This is manually reset. */
|
||||
HANDLE have_data_ev;
|
||||
/* This is automatically reset. */
|
||||
HANDLE have_space_ev;
|
||||
/* This is manually reset but actually only triggered once. */
|
||||
HANDLE close_ev;
|
||||
|
||||
size_t readpos, writepos;
|
||||
char buffer[READBUF_SIZE];
|
||||
};
|
||||
|
||||
|
||||
static struct
|
||||
{
|
||||
volatile int used;
|
||||
int fd;
|
||||
struct reader_context_s *context;
|
||||
} reader_table[MAX_READERS];
|
||||
static int reader_table_size= MAX_READERS;
|
||||
DEFINE_STATIC_LOCK (reader_table_lock);
|
||||
|
||||
|
||||
struct writer_context_s
|
||||
{
|
||||
HANDLE file_hd;
|
||||
int file_sock;
|
||||
HANDLE thread_hd;
|
||||
int refcount;
|
||||
|
||||
DECLARE_LOCK (mutex);
|
||||
|
||||
int stop_me;
|
||||
int error;
|
||||
int error_code;
|
||||
|
||||
/* This is manually reset. */
|
||||
HANDLE have_data;
|
||||
HANDLE is_empty;
|
||||
HANDLE close_ev;
|
||||
size_t nbytes;
|
||||
char buffer[WRITEBUF_SIZE];
|
||||
};
|
||||
|
||||
|
||||
static struct
|
||||
{
|
||||
volatile int used;
|
||||
int fd;
|
||||
struct writer_context_s *context;
|
||||
} writer_table[MAX_WRITERS];
|
||||
static int writer_table_size= MAX_WRITERS;
|
||||
DEFINE_STATIC_LOCK (writer_table_lock);
|
||||
|
||||
|
||||
static int
|
||||
get_desired_thread_priority (void)
|
||||
{
|
||||
@ -241,6 +234,9 @@ get_desired_thread_priority (void)
|
||||
}
|
||||
|
||||
|
||||
/* The reader thread. Created on the fly by gpgme_io_read and
|
||||
* destroyed by destroy_reader. Note that this functions works with a
|
||||
* copy of the value of the HANDLE variable frm the FS_TABLE. */
|
||||
static DWORD CALLBACK
|
||||
reader (void *arg)
|
||||
{
|
||||
@ -382,14 +378,18 @@ reader (void *arg)
|
||||
}
|
||||
|
||||
|
||||
/* Create a new reader thread and return its context object. The
|
||||
* input is a HANDLE or a socket SOCK. This function may not call any
|
||||
* fd based functions because the caller already holds a lock on the
|
||||
* fd_table. */
|
||||
static struct reader_context_s *
|
||||
create_reader (int fd)
|
||||
create_reader (HANDLE handle, int sock)
|
||||
{
|
||||
struct reader_context_s *ctx;
|
||||
SECURITY_ATTRIBUTES sec_attr;
|
||||
DWORD tid;
|
||||
|
||||
TRACE_BEG (DEBUG_SYSIO, "gpgme:create_reader", fd);
|
||||
TRACE_BEG (DEBUG_SYSIO, "gpgme:create_reader", handle);
|
||||
|
||||
memset (&sec_attr, 0, sizeof sec_attr);
|
||||
sec_attr.nLength = sizeof sec_attr;
|
||||
@ -402,17 +402,8 @@ create_reader (int fd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
|
||||
{
|
||||
TRACE_SYSERR (EIO);
|
||||
free (ctx);
|
||||
return NULL;
|
||||
}
|
||||
TRACE_LOG4 ("fd=%d -> handle=%p socket=%d dupfrom=%d",
|
||||
fd, fd_table[fd].handle, fd_table[fd].socket,
|
||||
fd_table[fd].dup_from);
|
||||
ctx->file_hd = fd_table[fd].handle;
|
||||
ctx->file_sock = fd_table[fd].socket;
|
||||
ctx->file_hd = handle;
|
||||
ctx->file_sock = sock;
|
||||
|
||||
ctx->refcount = 1;
|
||||
ctx->have_data_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
|
||||
@ -511,37 +502,44 @@ destroy_reader (struct reader_context_s *ctx)
|
||||
|
||||
|
||||
/* Find a reader context or create a new one. Note that the reader
|
||||
context will last until a _gpgme_io_close. */
|
||||
* context will last until a _gpgme_io_close. NULL is returned for a
|
||||
* bad FD or for other errors. */
|
||||
static struct reader_context_s *
|
||||
find_reader (int fd)
|
||||
{
|
||||
struct reader_context_s *rd = NULL;
|
||||
int i;
|
||||
|
||||
LOCK (reader_table_lock);
|
||||
for (i = 0; i < reader_table_size; i++)
|
||||
if (reader_table[i].used && reader_table[i].fd == fd)
|
||||
rd = reader_table[i].context;
|
||||
TRACE_BEG0 (DEBUG_SYSIO, "gpgme:find_reader", fd, "");
|
||||
|
||||
LOCK (fd_table_lock);
|
||||
if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
|
||||
{
|
||||
UNLOCK (fd_table_lock);
|
||||
gpg_err_set_errno (EBADF);
|
||||
TRACE_SUC0 ("EBADF");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rd = fd_table[fd].reader;
|
||||
if (rd)
|
||||
{
|
||||
UNLOCK (reader_table_lock);
|
||||
return rd;
|
||||
UNLOCK (fd_table_lock);
|
||||
TRACE_SUC1 ("rd=%p", rd);
|
||||
return rd; /* Return already initialized reader thread object. */
|
||||
}
|
||||
|
||||
for (i = 0; i < reader_table_size; i++)
|
||||
if (!reader_table[i].used)
|
||||
break;
|
||||
/* Create a new reader thread. */
|
||||
TRACE_LOG4 ("fd=%d -> handle=%p socket=%d dupfrom=%d creating reader",
|
||||
fd, fd_table[fd].handle, fd_table[fd].socket,
|
||||
fd_table[fd].dup_from);
|
||||
rd = create_reader (fd_table[fd].handle, fd_table[fd].socket);
|
||||
if (!rd)
|
||||
gpg_err_set_errno (EIO);
|
||||
else
|
||||
fd_table[fd].reader = rd;
|
||||
|
||||
if (i != reader_table_size)
|
||||
{
|
||||
rd = create_reader (fd);
|
||||
reader_table[i].fd = fd;
|
||||
reader_table[i].context = rd;
|
||||
reader_table[i].used = 1;
|
||||
}
|
||||
|
||||
UNLOCK (reader_table_lock);
|
||||
UNLOCK (fd_table_lock);
|
||||
TRACE_SUC1 ("rd=%p (new)", rd);
|
||||
return rd;
|
||||
}
|
||||
|
||||
@ -556,10 +554,7 @@ _gpgme_io_read (int fd, void *buffer, size_t count)
|
||||
|
||||
ctx = find_reader (fd);
|
||||
if (!ctx)
|
||||
{
|
||||
gpg_err_set_errno (EBADF);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
if (ctx->eof_shortcut)
|
||||
return TRACE_SYSRES (0);
|
||||
|
||||
@ -734,13 +729,13 @@ writer (void *arg)
|
||||
|
||||
|
||||
static struct writer_context_s *
|
||||
create_writer (int fd)
|
||||
create_writer (HANDLE handle, int sock)
|
||||
{
|
||||
struct writer_context_s *ctx;
|
||||
SECURITY_ATTRIBUTES sec_attr;
|
||||
DWORD tid;
|
||||
|
||||
TRACE_BEG (DEBUG_SYSIO, "gpgme:create_writer", fd);
|
||||
TRACE_BEG (DEBUG_SYSIO, "gpgme:create_writer", handle);
|
||||
|
||||
memset (&sec_attr, 0, sizeof sec_attr);
|
||||
sec_attr.nLength = sizeof sec_attr;
|
||||
@ -753,17 +748,8 @@ create_writer (int fd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
|
||||
{
|
||||
TRACE_SYSERR (EIO);
|
||||
free (ctx);
|
||||
return NULL;
|
||||
}
|
||||
TRACE_LOG4 ("fd=%d -> handle=%p socket=%d dupfrom=%d",
|
||||
fd, fd_table[fd].handle, fd_table[fd].socket,
|
||||
fd_table[fd].dup_from);
|
||||
ctx->file_hd = fd_table[fd].handle;
|
||||
ctx->file_sock = fd_table[fd].socket;
|
||||
ctx->file_hd = handle;
|
||||
ctx->file_sock = sock;
|
||||
|
||||
ctx->refcount = 1;
|
||||
ctx->have_data = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
|
||||
@ -840,37 +826,44 @@ destroy_writer (struct writer_context_s *ctx)
|
||||
|
||||
|
||||
/* Find a writer context or create a new one. Note that the writer
|
||||
* context will last until a _gpgme_io_close. */
|
||||
* context will last until a _gpgme_io_close. NULL is returned for a
|
||||
* bad FD or for other errors. */
|
||||
static struct writer_context_s *
|
||||
find_writer (int fd)
|
||||
{
|
||||
struct writer_context_s *wt = NULL;
|
||||
int i;
|
||||
|
||||
LOCK (writer_table_lock);
|
||||
for (i = 0; i < writer_table_size; i++)
|
||||
if (writer_table[i].used && writer_table[i].fd == fd)
|
||||
wt = writer_table[i].context;
|
||||
TRACE_BEG0 (DEBUG_SYSIO, "gpgme:find_writer", fd, "");
|
||||
|
||||
LOCK (fd_table_lock);
|
||||
if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
|
||||
{
|
||||
UNLOCK (fd_table_lock);
|
||||
gpg_err_set_errno (EBADF);
|
||||
TRACE_SUC0 ("EBADF");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wt = fd_table[fd].writer;
|
||||
if (wt)
|
||||
{
|
||||
UNLOCK (writer_table_lock);
|
||||
return wt;
|
||||
UNLOCK (fd_table_lock);
|
||||
TRACE_SUC1 ("wt=%p", wt);
|
||||
return wt; /* Return already initialized writer thread object. */
|
||||
}
|
||||
|
||||
for (i = 0; i < writer_table_size; i++)
|
||||
if (!writer_table[i].used)
|
||||
break;
|
||||
/* Create a new writer thread. */
|
||||
TRACE_LOG4 ("fd=%d -> handle=%p socket=%d dupfrom=%d creating writer",
|
||||
fd, fd_table[fd].handle, fd_table[fd].socket,
|
||||
fd_table[fd].dup_from);
|
||||
wt = create_writer (fd_table[fd].handle, fd_table[fd].socket);
|
||||
if (!wt)
|
||||
gpg_err_set_errno (EIO);
|
||||
else
|
||||
fd_table[fd].writer = wt;
|
||||
|
||||
if (i != writer_table_size)
|
||||
{
|
||||
wt = create_writer (fd);
|
||||
writer_table[i].fd = fd;
|
||||
writer_table[i].context = wt;
|
||||
writer_table[i].used = 1;
|
||||
}
|
||||
|
||||
UNLOCK (writer_table_lock);
|
||||
UNLOCK (fd_table_lock);
|
||||
TRACE_SUC1 ("wt=%p (new)", wt);
|
||||
return wt;
|
||||
}
|
||||
|
||||
@ -931,7 +924,7 @@ _gpgme_io_write (int fd, const void *buffer, size_t count)
|
||||
ctx->nbytes = count;
|
||||
|
||||
/* We have to reset the is_empty event early, because it is also
|
||||
used by the select() implementation to probe the channel. */
|
||||
* used by the select() implementation to probe the channel. */
|
||||
if (!ResetEvent (ctx->is_empty))
|
||||
{
|
||||
TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
|
||||
@ -1035,7 +1028,10 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
|
||||
wh = hd;
|
||||
}
|
||||
|
||||
/* Put the HANDLEs of the new pipe into the file descriptor table. */
|
||||
/* Put the HANDLEs of the new pipe into the file descriptor table.
|
||||
* Note that we don't need to lock the table because we have just
|
||||
* acquired these two fresh fds and they are not known by any other
|
||||
* thread. */
|
||||
fd_table[rfd].handle = rh;
|
||||
fd_table[wfd].handle = wh;
|
||||
|
||||
@ -1046,22 +1042,27 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
|
||||
}
|
||||
|
||||
|
||||
/* Close out File descriptor FD. */
|
||||
int
|
||||
_gpgme_io_close (int fd)
|
||||
{
|
||||
int i;
|
||||
_gpgme_close_notify_handler_t handler = NULL;
|
||||
void *value = NULL;
|
||||
|
||||
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd);
|
||||
|
||||
if (fd == -1)
|
||||
if (fd < 0)
|
||||
{
|
||||
gpg_err_set_errno (EBADF);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
|
||||
|
||||
LOCK (fd_table_lock);
|
||||
/* Check the size in the locked state because we may eventually add
|
||||
* code to change that size. */
|
||||
if (fd >= fd_table_size || !fd_table[fd].used)
|
||||
{
|
||||
UNLOCK (fd_table_lock);
|
||||
gpg_err_set_errno (EBADF);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
@ -1070,48 +1071,22 @@ _gpgme_io_close (int fd)
|
||||
fd, fd_table[fd].handle, fd_table[fd].socket,
|
||||
fd_table[fd].dup_from);
|
||||
|
||||
LOCK (reader_table_lock);
|
||||
for (i = 0; i < reader_table_size; i++)
|
||||
if (fd_table[fd].reader)
|
||||
{
|
||||
if (reader_table[i].used && reader_table[i].fd == fd)
|
||||
{
|
||||
destroy_reader (reader_table[i].context);
|
||||
reader_table[i].context = NULL;
|
||||
reader_table[i].used = 0;
|
||||
break;
|
||||
destroy_reader (fd_table[fd].reader);
|
||||
fd_table[fd].reader = NULL;
|
||||
}
|
||||
}
|
||||
UNLOCK (reader_table_lock);
|
||||
|
||||
LOCK (writer_table_lock);
|
||||
for (i = 0; i < writer_table_size; i++)
|
||||
if (fd_table[fd].writer)
|
||||
{
|
||||
if (writer_table[i].used && writer_table[i].fd == fd)
|
||||
{
|
||||
destroy_writer (writer_table[i].context);
|
||||
writer_table[i].context = NULL;
|
||||
writer_table[i].used = 0;
|
||||
break;
|
||||
destroy_writer (fd_table[fd].writer);
|
||||
fd_table[fd].writer = NULL;
|
||||
}
|
||||
}
|
||||
UNLOCK (writer_table_lock);
|
||||
|
||||
LOCK (notify_table_lock);
|
||||
for (i = 0; i < DIM (notify_table); i++)
|
||||
{
|
||||
if (notify_table[i].inuse && notify_table[i].fd == fd)
|
||||
{
|
||||
handler = notify_table[i].handler;
|
||||
value = notify_table[i].value;
|
||||
notify_table[i].handler = NULL;
|
||||
notify_table[i].value = NULL;
|
||||
notify_table[i].inuse = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
UNLOCK (notify_table_lock);
|
||||
if (handler)
|
||||
handler (fd, value);
|
||||
/* FIXME: The handler may not use any fd fucntion becuase the table
|
||||
* is locked. Can we avoid this? */
|
||||
handler = fd_table[fd].notify.handler;
|
||||
value = fd_table[fd].notify.value;
|
||||
|
||||
if (fd_table[fd].dup_from == -1)
|
||||
{
|
||||
@ -1122,6 +1097,7 @@ _gpgme_io_close (int fd)
|
||||
TRACE_LOG1 ("CloseHandle failed: ec=%d", (int) GetLastError ());
|
||||
/* FIXME: Should translate the error code. */
|
||||
gpg_err_set_errno (EIO);
|
||||
UNLOCK (fd_table_lock);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
}
|
||||
@ -1129,49 +1105,50 @@ _gpgme_io_close (int fd)
|
||||
{
|
||||
if (closesocket (fd_table[fd].socket))
|
||||
{
|
||||
TRACE_LOG1 ("closesocket failed: ec=%d", (int) WSAGetLastError ());
|
||||
TRACE_LOG1 ("closesocket failed: ec=%d", (int)WSAGetLastError ());
|
||||
/* FIXME: Should translate the error code. */
|
||||
gpg_err_set_errno (EIO);
|
||||
UNLOCK (fd_table_lock);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
release_fd (fd);
|
||||
UNLOCK (fd_table_lock);
|
||||
|
||||
/* Run the notification callback. */
|
||||
if (handler)
|
||||
handler (fd, value);
|
||||
|
||||
release_fd (fd); /* FIXME: We should have a release_fd_locked () */
|
||||
|
||||
return TRACE_SYSRES (0);
|
||||
}
|
||||
|
||||
|
||||
/* Set a close notification callback which is called right after FD
|
||||
* has been closed but before its slot (ie. the FD number) is beeing
|
||||
* released. Tha HANDLER may thus use the provided value of the FD
|
||||
* but it may not pass it to any I/O functions. Note: Only the last
|
||||
* handler set for an FD is used. */
|
||||
int
|
||||
_gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler,
|
||||
void *value)
|
||||
{
|
||||
int i;
|
||||
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd,
|
||||
"close_handler=%p/%p", handler, value);
|
||||
|
||||
assert (fd != -1);
|
||||
|
||||
LOCK (notify_table_lock);
|
||||
for (i=0; i < DIM (notify_table); i++)
|
||||
if (notify_table[i].inuse && notify_table[i].fd == fd)
|
||||
break;
|
||||
if (i == DIM (notify_table))
|
||||
for (i = 0; i < DIM (notify_table); i++)
|
||||
if (!notify_table[i].inuse)
|
||||
break;
|
||||
if (i == DIM (notify_table))
|
||||
LOCK (fd_table_lock);
|
||||
if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
|
||||
{
|
||||
UNLOCK (notify_table_lock);
|
||||
gpg_err_set_errno (EINVAL);
|
||||
return TRACE_SYSRES (-1);
|
||||
UNLOCK (fd_table_lock);
|
||||
gpg_err_set_errno (EBADF);
|
||||
return TRACE_SYSRES (-1);;
|
||||
}
|
||||
notify_table[i].fd = fd;
|
||||
notify_table[i].handler = handler;
|
||||
notify_table[i].value = value;
|
||||
notify_table[i].inuse = 1;
|
||||
UNLOCK (notify_table_lock);
|
||||
|
||||
fd_table[fd].notify.handler = handler;
|
||||
fd_table[fd].notify.value = value;
|
||||
UNLOCK (fd_table_lock);
|
||||
return TRACE_SYSRES (0);
|
||||
}
|
||||
|
||||
@ -1267,6 +1244,10 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
|
||||
|
||||
TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path,
|
||||
"path=%s", path);
|
||||
|
||||
(void)atfork;
|
||||
(void)atforkvalue;
|
||||
|
||||
i = 0;
|
||||
while (argv[i])
|
||||
{
|
||||
@ -1374,6 +1355,7 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
|
||||
_gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId);
|
||||
|
||||
/* Insert the inherited handles. */
|
||||
LOCK (fd_table_lock);
|
||||
for (i = 0; fd_list[i].fd != -1; i++)
|
||||
{
|
||||
int fd = fd_list[i].fd;
|
||||
@ -1381,7 +1363,7 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
|
||||
HANDLE hd = INVALID_HANDLE_VALUE;
|
||||
|
||||
/* Make it inheritable for the wrapper process. */
|
||||
if (fd >= 0 && fd < MAX_SLAFD && fd_table[fd].used)
|
||||
if (fd >= 0 && fd < fd_table_size && fd_table[fd].used)
|
||||
ohd = fd_table[fd].handle;
|
||||
|
||||
if (!DuplicateHandle (GetCurrentProcess(), ohd,
|
||||
@ -1401,6 +1383,7 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
|
||||
|
||||
/* FIXME: Should translate the error code. */
|
||||
gpg_err_set_errno (EIO);
|
||||
UNLOCK (fd_table_lock);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
/* Return the child name of this handle. */
|
||||
@ -1454,6 +1437,8 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
|
||||
free (tmp_name);
|
||||
free (arg_string);
|
||||
|
||||
UNLOCK (fd_table_lock);
|
||||
|
||||
TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, "
|
||||
"dwProcessID=%d, dwThreadId=%d",
|
||||
pi.hProcess, pi.hThread,
|
||||
@ -1528,6 +1513,8 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
|
||||
{
|
||||
if (fds[i].for_read)
|
||||
{
|
||||
/* FIXME: A find_reader_locked() along with separate
|
||||
* lock calls might be a better appaoched here. */
|
||||
struct reader_context_s *ctx = find_reader (fds[i].fd);
|
||||
|
||||
if (!ctx)
|
||||
@ -1581,11 +1568,11 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
|
||||
code = WaitForMultipleObjects (nwait, waitbuf, 0, nonblock ? 0 : 1000);
|
||||
if (code >= WAIT_OBJECT_0 && code < WAIT_OBJECT_0 + nwait)
|
||||
{
|
||||
/* This WFMO is a really silly function: It does return either
|
||||
/* The WFMO is a really silly function: It does return either
|
||||
the index of the signaled object or if 2 objects have been
|
||||
signalled at the same time, the index of the object with the
|
||||
lowest object is returned - so and how do we find out how
|
||||
many objects have been signaled???. The only solution I can
|
||||
many objects have been signaled?. The only solution I can
|
||||
imagine is to test each object starting with the returned
|
||||
index individually - how dull. */
|
||||
any = 0;
|
||||
@ -1668,13 +1655,15 @@ _gpgme_io_subsystem_init (void)
|
||||
}
|
||||
|
||||
|
||||
/* Write the printable version of FD to the buffer BUF of length
|
||||
BUFLEN. The printable version is the representation on the command
|
||||
line that the child process expects. */
|
||||
/* Write the printable version of FD to BUFFER which has an allocated
|
||||
* length of BUFLEN. The printable version is the representation on
|
||||
* the command line that the child process expects. Note that this
|
||||
* works closely together with the gpgme-32spawn wrapper process which
|
||||
* translates these command line args to the real handles. */
|
||||
int
|
||||
_gpgme_io_fd2str (char *buf, int buflen, int fd)
|
||||
_gpgme_io_fd2str (char *buffer, int buflen, int fd)
|
||||
{
|
||||
return snprintf (buf, buflen, "%d", fd);
|
||||
return snprintf (buffer, buflen, "%d", fd);
|
||||
}
|
||||
|
||||
|
||||
@ -1684,60 +1673,47 @@ _gpgme_io_dup (int fd)
|
||||
int newfd;
|
||||
struct reader_context_s *rd_ctx;
|
||||
struct writer_context_s *wt_ctx;
|
||||
int i;
|
||||
|
||||
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_dup", fd);
|
||||
|
||||
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
|
||||
LOCK (fd_table_lock);
|
||||
if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
|
||||
{
|
||||
gpg_err_set_errno (EINVAL);
|
||||
UNLOCK (fd_table_lock);
|
||||
gpg_err_set_errno (EBADF);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
newfd = new_fd();
|
||||
if (newfd == -1)
|
||||
{
|
||||
UNLOCK (fd_table_lock);
|
||||
gpg_err_set_errno (EMFILE);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
fd_table[newfd].handle = fd_table[fd].handle;
|
||||
fd_table[newfd].socket = fd_table[fd].socket;
|
||||
fd_table[newfd].dup_from = fd;
|
||||
|
||||
UNLOCK (fd_table_lock);
|
||||
|
||||
rd_ctx = find_reader (fd);
|
||||
if (rd_ctx)
|
||||
{
|
||||
/* No need for locking, as the only races are against the reader
|
||||
thread itself, which doesn't touch refcount. */
|
||||
/* No need for locking in the context, as the only races are
|
||||
* against the reader thread itself, which doesn't touch
|
||||
* refcount. NEWFD initializes a freshly allocated slot and
|
||||
* does not need locking either. */
|
||||
rd_ctx->refcount++;
|
||||
|
||||
LOCK (reader_table_lock);
|
||||
for (i = 0; i < reader_table_size; i++)
|
||||
if (!reader_table[i].used)
|
||||
break;
|
||||
/* FIXME. */
|
||||
assert (i != reader_table_size);
|
||||
reader_table[i].fd = newfd;
|
||||
reader_table[i].context = rd_ctx;
|
||||
reader_table[i].used = 1;
|
||||
UNLOCK (reader_table_lock);
|
||||
fd_table[newfd].reader = rd_ctx;
|
||||
}
|
||||
|
||||
wt_ctx = find_writer (fd);
|
||||
if (wt_ctx)
|
||||
{
|
||||
/* No need for locking, as the only races are against the writer
|
||||
thread itself, which doesn't touch refcount. */
|
||||
wt_ctx->refcount++;
|
||||
|
||||
LOCK (writer_table_lock);
|
||||
for (i = 0; i < writer_table_size; i++)
|
||||
if (!writer_table[i].used)
|
||||
break;
|
||||
/* FIXME. */
|
||||
assert (i != writer_table_size);
|
||||
writer_table[i].fd = newfd;
|
||||
writer_table[i].context = wt_ctx;
|
||||
writer_table[i].used = 1;
|
||||
UNLOCK (writer_table_lock);
|
||||
fd_table[newfd].writer = wt_ctx;
|
||||
}
|
||||
|
||||
return TRACE_SYSRES (newfd);
|
||||
@ -1815,17 +1791,22 @@ int
|
||||
_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
|
||||
{
|
||||
int res;
|
||||
int sock;
|
||||
|
||||
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd,
|
||||
"addr=%p, addrlen=%i", addr, addrlen);
|
||||
|
||||
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
|
||||
LOCK (fd_table_lock);
|
||||
if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
|
||||
{
|
||||
gpg_err_set_errno (EBADF);
|
||||
UNLOCK (fd_table_lock);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
sock = fd_table[fd].socket;
|
||||
UNLOCK (fd_table_lock);
|
||||
|
||||
res = connect (fd_table[fd].socket, addr, addrlen);
|
||||
res = connect (sock, addr, addrlen);
|
||||
if (res)
|
||||
{
|
||||
gpg_err_set_errno (wsa2errno (WSAGetLastError ()));
|
||||
|
Loading…
Reference in New Issue
Block a user