From c76ded2ca0bb6136205e69caa073bf19944ae509 Mon Sep 17 00:00:00 2001 From: Ken Brown Date: Thu, 2 Apr 2020 13:47:18 -0400 Subject: [PATCH] Cygwin: FIFO: allow fc_handler list to grow dynamically Make fc_handler a pointer to malloc'd memory instead of a fixed-size array. The size is now a new data member 'shandlers'. Call realloc in add_client_handler if we need to grow the array. free fc_handler in close. As long as we're touching that code, also remove an unneeded lock. --- winsup/cygwin/fhandler.h | 6 ++--- winsup/cygwin/fhandler_fifo.cc | 41 +++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index bd44da5cd..4f42cf1b8 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1268,7 +1268,6 @@ public: }; #define CYGWIN_FIFO_PIPE_NAME_LEN 47 -#define MAX_CLIENTS 64 /* The last three are the ones we try to read from. */ enum fifo_client_connect_state @@ -1351,8 +1350,9 @@ class fhandler_fifo: public fhandler_base UNICODE_STRING pipe_name; WCHAR pipe_name_buf[CYGWIN_FIFO_PIPE_NAME_LEN + 1]; bool _maybe_eof; - fifo_client_handler fc_handler[MAX_CLIENTS]; - int nhandlers; + fifo_client_handler *fc_handler; /* Dynamically growing array. */ + int shandlers; /* Size (capacity) of the array. */ + int nhandlers; /* Number of elements in the array. */ af_unix_spinlock_t _fifo_client_lock; bool reader, writer, duplexer; size_t max_atomic_write; diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc index 0b9b33785..595e55ad9 100644 --- a/winsup/cygwin/fhandler_fifo.cc +++ b/winsup/cygwin/fhandler_fifo.cc @@ -70,7 +70,8 @@ static NO_COPY fifo_reader_id_t null_fr_id = { .winpid = 0, .fh = NULL }; fhandler_fifo::fhandler_fifo (): fhandler_base (), read_ready (NULL), write_ready (NULL), writer_opening (NULL), - cancel_evt (NULL), thr_sync_evt (NULL), _maybe_eof (false), nhandlers (0), + cancel_evt (NULL), thr_sync_evt (NULL), _maybe_eof (false), + fc_handler (NULL), shandlers (0), nhandlers (0), reader (false), writer (false), duplexer (false), max_atomic_write (DEFAULT_PIPEBUFSIZE), me (null_fr_id), shmem_handle (NULL), shmem (NULL) @@ -287,27 +288,28 @@ fhandler_fifo::wait_open_pipe (HANDLE& ph) int fhandler_fifo::add_client_handler () { - int ret = -1; fifo_client_handler fc; HANDLE ph = NULL; - if (nhandlers == MAX_CLIENTS) + if (nhandlers >= shandlers) { - set_errno (EMFILE); - goto out; + void *temp = realloc (fc_handler, + (shandlers += 64) * sizeof (fc_handler[0])); + if (!temp) + { + shandlers -= 64; + set_errno (ENOMEM); + return -1; + } + fc_handler = (fifo_client_handler *) temp; } ph = create_pipe_instance (); if (!ph) - goto out; - else - { - ret = 0; - fc.h = ph; - fc.state = fc_listening; - fc_handler[nhandlers++] = fc; - } -out: - return ret; + return -1; + fc.h = ph; + fc.state = fc_listening; + fc_handler[nhandlers++] = fc; + return 0; } void @@ -1067,10 +1069,10 @@ fhandler_fifo::close () NtClose (write_ready); if (writer_opening) NtClose (writer_opening); - fifo_client_lock (); for (int i = 0; i < nhandlers; i++) fc_handler[i].close (); - fifo_client_unlock (); + if (fc_handler) + free (fc_handler); return fhandler_base::close (); } @@ -1130,7 +1132,8 @@ fhandler_fifo::dup (fhandler_base *child, int flags) fhf->fifo_client_unlock (); /* Clear fc_handler list; the child never starts as owner. */ - fhf->nhandlers = 0; + fhf->nhandlers = fhf->shandlers = 0; + fhf->fc_handler = NULL; if (!DuplicateHandle (GetCurrentProcess (), shmem_handle, GetCurrentProcess (), &fhf->shmem_handle, @@ -1206,6 +1209,8 @@ fhandler_fifo::fixup_after_exec () if (reopen_shmem () < 0) api_fatal ("Can't reopen shared memory during exec, %E"); + fc_handler = NULL; + nhandlers = shandlers = 0; me.winpid = GetCurrentProcessId (); if (!(cancel_evt = create_event ())) api_fatal ("Can't create reader thread cancel event during exec, %E");