From 338e9edfdb9239f1c9d4409f6d08d79a9d6f285b Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 1 Nov 2018 09:53:48 +0100 Subject: [PATCH] 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 --- src/w32-io.c | 511 +++++++++++++++++++++++++-------------------------- 1 file changed, 246 insertions(+), 265 deletions(-) diff --git a/src/w32-io.c b/src/w32-io.c index e3201b7b..ad1e330c 100644 --- a/src/w32-io.c +++ b/src/w32-io.c @@ -43,13 +43,73 @@ #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 - * only an index into this table. Never ever pass such an fd to any + * only an index into this table. Never ever pass such an fd to any * other function except for those implemented here. */ static struct { @@ -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); - } + 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) - return TRACE_SYSRES (-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 ()));