public inbox for cygwin-cvs@sourceware.org help / color / mirror / Atom feed
From: Ken Brown <kbrown@sourceware.org> To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: FIFO: add shared memory Date: Fri, 8 May 2020 11:29:57 +0000 (GMT) [thread overview] Message-ID: <20200508112957.709083971C43@sourceware.org> (raw) https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=878eb224622cd3bfc485fdf94a6c2f65e810fa19 commit 878eb224622cd3bfc485fdf94a6c2f65e810fa19 Author: Ken Brown <kbrown@cornell.edu> Date: Tue Mar 17 12:29:56 2020 -0400 Cygwin: FIFO: add shared memory Even though we currently allow a FIFO to be opened for reading only once, we can still have more than one reader open because of dup and fork. Add a named shared memory section accessible to all readers of a given FIFO. In future commits we will add information needed by all readers to this section Add a class fifo_shmem_t that lets us access this information. Add a method create_shmem that is called when a reader opens, and add a method reopen_shmem that is called by dup, fork, and exec. (Each new reader needs its own view of the shared memory.) Diff: --- winsup/cygwin/fhandler.h | 13 ++++++ winsup/cygwin/fhandler_fifo.cc | 97 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 4 deletions(-) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 5e6a1d1db..8d6b94021 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1300,6 +1300,11 @@ struct fifo_client_handler int pipe_state (); }; +/* Info needed by all readers of a FIFO, stored in named shared memory. */ +class fifo_shmem_t +{ +}; + class fhandler_fifo: public fhandler_base { /* Handles to named events shared by all fhandlers for a given FIFO. */ @@ -1319,6 +1324,10 @@ class fhandler_fifo: public fhandler_base af_unix_spinlock_t _fifo_client_lock; bool reader, writer, duplexer; size_t max_atomic_write; + + HANDLE shmem_handle; + fifo_shmem_t *shmem; + bool __reg2 wait (HANDLE); static NTSTATUS npfs_handle (HANDLE &); HANDLE create_pipe_instance (bool); @@ -1330,6 +1339,9 @@ class fhandler_fifo: public fhandler_base void record_connection (fifo_client_handler&, fifo_client_connect_state = fc_connected); + int create_shmem (); + int reopen_shmem (); + public: fhandler_fifo (); bool hit_eof (); @@ -1341,6 +1353,7 @@ public: DWORD fifo_reader_thread_func (); void fifo_client_lock () { _fifo_client_lock.lock (); } void fifo_client_unlock () { _fifo_client_lock.unlock (); } + int open (int, mode_t); off_t lseek (off_t offset, int whence); int close (); diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc index 09a7eb321..9a0db3f33 100644 --- a/winsup/cygwin/fhandler_fifo.cc +++ b/winsup/cygwin/fhandler_fifo.cc @@ -70,7 +70,8 @@ fhandler_fifo::fhandler_fifo (): read_ready (NULL), write_ready (NULL), writer_opening (NULL), cancel_evt (NULL), thr_sync_evt (NULL), _maybe_eof (false), nhandlers (0), reader (false), writer (false), duplexer (false), - max_atomic_write (DEFAULT_PIPEBUFSIZE) + max_atomic_write (DEFAULT_PIPEBUFSIZE), + shmem_handle (NULL), shmem (NULL) { pipe_name_buf[0] = L'\0'; need_fork_fixup (true); @@ -441,6 +442,67 @@ canceled: return 0; } +int +fhandler_fifo::create_shmem () +{ + HANDLE sect; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + LARGE_INTEGER size = { .QuadPart = sizeof (fifo_shmem_t) }; + SIZE_T viewsize = sizeof (fifo_shmem_t); + PVOID addr = NULL; + UNICODE_STRING uname; + WCHAR shmem_name[MAX_PATH]; + + __small_swprintf (shmem_name, L"fifo-shmem.%08x.%016X", get_dev (), + get_ino ()); + RtlInitUnicodeString (&uname, shmem_name); + InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT, + get_shared_parent_dir (), NULL); + status = NtCreateSection (§, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY + | SECTION_MAP_READ | SECTION_MAP_WRITE, + &attr, &size, PAGE_READWRITE, SEC_COMMIT, NULL); + if (status == STATUS_OBJECT_NAME_COLLISION) + status = NtOpenSection (§, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY + | SECTION_MAP_READ | SECTION_MAP_WRITE, &attr); + if (!NT_SUCCESS (status)) + { + __seterrno_from_nt_status (status); + return -1; + } + status = NtMapViewOfSection (sect, NtCurrentProcess (), &addr, 0, viewsize, + NULL, &viewsize, ViewShare, 0, PAGE_READWRITE); + if (!NT_SUCCESS (status)) + { + NtClose (sect); + __seterrno_from_nt_status (status); + return -1; + } + shmem_handle = sect; + shmem = (fifo_shmem_t *) addr; + return 0; +} + +/* shmem_handle must be valid when this is called. */ +int +fhandler_fifo::reopen_shmem () +{ + NTSTATUS status; + SIZE_T viewsize = sizeof (fifo_shmem_t); + PVOID addr = NULL; + + status = NtMapViewOfSection (shmem_handle, NtCurrentProcess (), &addr, + 0, viewsize, NULL, &viewsize, ViewShare, + 0, PAGE_READWRITE); + if (!NT_SUCCESS (status)) + { + __seterrno_from_nt_status (status); + return -1; + } + shmem = (fifo_shmem_t *) addr; + return 0; +} + int fhandler_fifo::open (int flags, mode_t) { @@ -501,12 +563,15 @@ fhandler_fifo::open (int flags, mode_t) goto err_close_write_ready; } - /* If we're reading, signal read_ready and start the fifo_reader_thread. */ + /* If we're reading, signal read_ready, create the shared memory, + and start the fifo_reader_thread. */ if (reader) { SetEvent (read_ready); - if (!(cancel_evt = create_event ())) + if (create_shmem () < 0) goto err_close_writer_opening; + if (!(cancel_evt = create_event ())) + goto err_close_shmem; if (!(thr_sync_evt = create_event ())) goto err_close_cancel_evt; new cygthread (fifo_reader_thread, this, "fifo_reader", thr_sync_evt); @@ -615,6 +680,9 @@ err_close_reader: return 0; err_close_cancel_evt: NtClose (cancel_evt); +err_close_shmem: + NtUnmapViewOfSection (NtCurrentProcess (), shmem); + NtClose (shmem_handle); err_close_writer_opening: NtClose (writer_opening); err_close_write_ready: @@ -944,6 +1012,10 @@ fhandler_fifo::close () dup/fork/exec; we should only reset read_ready when the last one closes. */ ResetEvent (read_ready); + if (shmem) + NtUnmapViewOfSection (NtCurrentProcess (), shmem); + if (shmem_handle) + NtClose (shmem_handle); } if (read_ready) NtClose (read_ready); @@ -1014,6 +1086,15 @@ fhandler_fifo::dup (fhandler_base *child, int flags) /* Make sure the child starts unlocked. */ fhf->fifo_client_unlock (); + if (!DuplicateHandle (GetCurrentProcess (), shmem_handle, + GetCurrentProcess (), &fhf->shmem_handle, + 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS)) + { + __seterrno (); + goto err_close_writer_opening; + } + if (fhf->reopen_shmem () < 0) + goto err_close_shmem_handle; fifo_client_lock (); for (i = 0; i < nhandlers; i++) { @@ -1044,7 +1125,10 @@ err_close_cancel_evt: err_close_handlers: for (int j = 0; j < i; j++) fhf->fc_handler[j].close (); -/* err_close_writer_opening: */ + NtUnmapViewOfSection (GetCurrentProcess (), fhf->shmem); +err_close_shmem_handle: + NtClose (fhf->shmem_handle); +err_close_writer_opening: NtClose (fhf->writer_opening); err_close_write_ready: NtClose (fhf->write_ready); @@ -1066,6 +1150,9 @@ fhandler_fifo::fixup_after_fork (HANDLE parent) /* Make sure the child starts unlocked. */ fifo_client_unlock (); + fork_fixup (parent, shmem_handle, "shmem_handle"); + if (reopen_shmem () < 0) + api_fatal ("Can't reopen shared memory during fork, %E"); fifo_client_lock (); for (int i = 0; i < nhandlers; i++) fork_fixup (parent, fc_handler[i].h, "fc_handler[].h"); @@ -1087,6 +1174,8 @@ fhandler_fifo::fixup_after_exec () /* Make sure the child starts unlocked. */ fifo_client_unlock (); + if (reopen_shmem () < 0) + api_fatal ("Can't reopen shared memory during exec, %E"); if (!(cancel_evt = create_event ())) api_fatal ("Can't create reader thread cancel event during exec, %E"); if (!(thr_sync_evt = create_event ()))
reply other threads:[~2020-05-08 11:29 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200508112957.709083971C43@sourceware.org \ --to=kbrown@sourceware.org \ --cc=cygwin-cvs@sourceware.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).