From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2155) id B1B983848026; Fri, 21 May 2021 13:33:57 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B1B983848026 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Corinna Vinschen To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: POSIX msg queues: Convert mqd_t to a descriptor X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/master X-Git-Oldrev: c0949782b7dd123a78f5469ca9e088eb33f59030 X-Git-Newrev: 4fc922b2c8a5920304e3aca2f575de9627fa20a1 Message-Id: <20210521133357.B1B983848026@sourceware.org> Date: Fri, 21 May 2021 13:33:57 +0000 (GMT) X-BeenThere: cygwin-cvs@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin core component git logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 May 2021 13:33:57 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=4fc922b2c8a5920304e3aca2f575de9627fa20a1 commit 4fc922b2c8a5920304e3aca2f575de9627fa20a1 Author: Corinna Vinschen Date: Fri May 21 12:01:56 2021 +0200 Cygwin: POSIX msg queues: Convert mqd_t to a descriptor So far, the mqd_t type returned a pointer to an allocated area under the hood. The mutex and event objects attached to the message queue were implemented as inheritable types. As unfortunate side effect the HANDLEs to these objects were inherited by exec'd child processes, even though all other message queue properties are not inherted, per POSIX. Fix this by converting an mqd_t to a descriptor, and create a matching fhandler_mqueue object to handle various aspects of the message queues inside the fhandler. Especially, create the IPC objects as non-inheritable and duplicate the HANDLEs as part of the fixup_after_fork mechanism. Drop using mmap and create the memory map with NT functions. This allows to control duplication of handle and mapping in the forked child process, without the requirement to regenerate the map in the same spot. It also allows to dup() the descriptor, as on Linux, albeit this isn't implemented yet. This patch is the first cut. There's a bit more to do, like moving more functionality from the POSIX functions into the fhandler and making sure the mqd_t type can't be used in other descriptor-related functions willy-nilly. Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/Makefile.am | 1 + winsup/cygwin/devices.cc | 3 + winsup/cygwin/devices.h | 3 + winsup/cygwin/devices.in | 3 + winsup/cygwin/dtable.cc | 3 + winsup/cygwin/fhandler.h | 41 +++++++ winsup/cygwin/fhandler_mqueue.cc | 113 ++++++++++++++++++ winsup/cygwin/mqueue_types.h | 58 ++++++++++ winsup/cygwin/posix_ipc.cc | 240 +++++++++++++++++++-------------------- 9 files changed, 343 insertions(+), 122 deletions(-) diff --git a/winsup/cygwin/Makefile.am b/winsup/cygwin/Makefile.am index c43f72ff9..63383a834 100644 --- a/winsup/cygwin/Makefile.am +++ b/winsup/cygwin/Makefile.am @@ -234,6 +234,7 @@ DLL_FILES= \ fhandler_dsp.cc \ fhandler_fifo.cc \ fhandler_floppy.cc \ + fhandler_mqueue.cc \ fhandler_netdrive.cc \ fhandler_nodevice.cc \ fhandler_pipe.cc \ diff --git a/winsup/cygwin/devices.cc b/winsup/cygwin/devices.cc index 3875a43cd..6ef886db4 100644 --- a/winsup/cygwin/devices.cc +++ b/winsup/cygwin/devices.cc @@ -126,6 +126,9 @@ const _device dev_signalfd_storage = const _device dev_timerfd_storage = {"", {FH_TIMERFD}, "", exists_internal}; +const _device dev_mqueue_storage = + {"", {FH_MQUEUE}, "", exists_internal}; + const _device dev_socket_storage = {"", {FH_SOCKET}, "", exists_internal}; diff --git a/winsup/cygwin/devices.h b/winsup/cygwin/devices.h index 5a077c2ef..4310f435f 100644 --- a/winsup/cygwin/devices.h +++ b/winsup/cygwin/devices.h @@ -73,6 +73,7 @@ enum fh_devices FH_SIGNALFD= FHDEV (DEV_VIRTFS_MAJOR, 13), FH_TIMERFD = FHDEV (DEV_VIRTFS_MAJOR, 14), + FH_MQUEUE = FHDEV (DEV_VIRTFS_MAJOR, 15), DEV_FLOPPY_MAJOR = 2, FH_FLOPPY = FHDEV (DEV_FLOPPY_MAJOR, 0), @@ -406,6 +407,8 @@ extern const _device dev_signalfd_storage; #define signalfd_dev ((device *) &dev_signalfd_storage) extern const _device dev_timerfd_storage; #define timerfd_dev ((device *) &dev_timerfd_storage) +extern const _device dev_mqueue_storage; +#define mqueue_dev ((device *) &dev_mqueue_storage) extern const _device dev_piper_storage; #define piper_dev ((device *) &dev_piper_storage) extern const _device dev_pipew_storage; diff --git a/winsup/cygwin/devices.in b/winsup/cygwin/devices.in index 9a42951f6..f33510eb7 100644 --- a/winsup/cygwin/devices.in +++ b/winsup/cygwin/devices.in @@ -122,6 +122,9 @@ const _device dev_signalfd_storage = const _device dev_timerfd_storage = {"", {FH_TIMERFD}, "", exists_internal}; +const _device dev_mqueue_storage = + {"", {FH_MQUEUE}, "", exists_internal}; + const _device dev_socket_storage = {"", {FH_SOCKET}, "", exists_internal}; diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index 84149bd3f..8085e656e 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -581,6 +581,9 @@ fh_alloc (path_conv& pc) case FH_TIMERFD: fh = cnew (fhandler_timerfd); break; + case FH_MQUEUE: + fh = cnew (fhandler_mqueue); + break; case FH_TTY: if (!pc.isopen ()) { diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 9df617b99..38533974c 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -10,6 +10,7 @@ details. */ #include "pinfo.h" #include "tty.h" +#include "mqueue_types.h" #include #include #include @@ -448,6 +449,7 @@ public: virtual class fhandler_console *is_console () { return 0; } virtual class fhandler_signalfd *is_signalfd () { return NULL; } virtual class fhandler_timerfd *is_timerfd () { return NULL; } + virtual class fhandler_mqueue *is_mqueue () { return NULL; } virtual int is_windows () {return 0; } virtual void __reg3 raw_read (void *ptr, size_t& ulen); @@ -3101,6 +3103,44 @@ class fhandler_timerfd : public fhandler_base } }; +class fhandler_mqueue: public fhandler_base +{ + struct mq_info mqi; + +public: + fhandler_mqueue (); + fhandler_mqueue (void *) {} + ~fhandler_mqueue () {} + + fhandler_mqueue *is_mqueue () { return this; } + + char *get_proc_fd_name (char *); + + struct mq_info *mqinfo (const char *, int8_t *, HANDLE, size_t, mode_t, int); + struct mq_info *mqinfo () { return &mqi; } + + void fixup_after_fork (HANDLE); + + int __reg2 fstat (struct stat *buf); + int dup (fhandler_base *child, int); + int close (); + + void copy_from (fhandler_base *x) + { + pc.free_strings (); + *this = *reinterpret_cast (x); + _copy_from_reset_helper (); + } + + fhandler_mqueue *clone (cygheap_types malloc_type = HEAP_FHANDLER) + { + void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_mqueue)); + fhandler_mqueue *fh = new (ptr) fhandler_mqueue (ptr); + fh->copy_from (this); + return fh; + } +}; + struct fhandler_nodevice: public fhandler_base { fhandler_nodevice (); @@ -3142,6 +3182,7 @@ typedef union char __serial[sizeof (fhandler_serial)]; char __signalfd[sizeof (fhandler_signalfd)]; char __timerfd[sizeof (fhandler_timerfd)]; + char __mqueue[sizeof (fhandler_mqueue)]; char __socket_inet[sizeof (fhandler_socket_inet)]; char __socket_local[sizeof (fhandler_socket_local)]; #ifdef __WITH_AF_UNIX diff --git a/winsup/cygwin/fhandler_mqueue.cc b/winsup/cygwin/fhandler_mqueue.cc new file mode 100644 index 000000000..b3b6d4258 --- /dev/null +++ b/winsup/cygwin/fhandler_mqueue.cc @@ -0,0 +1,113 @@ +/* fhandler_mqueue.cc: fhandler for POSIX message queue + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#include "winsup.h" +#include "path.h" +#include "fhandler.h" +#include "dtable.h" + +fhandler_mqueue::fhandler_mqueue () : + fhandler_base () +{ + nohandle (true); + close_on_exec (true); +} + +struct mq_info * +fhandler_mqueue::mqinfo (const char *name, int8_t *mptr, HANDLE sect, + size_t size, mode_t mode, int flags) +{ + set_name (name); + mqinfo ()->mqi_hdr = (struct mq_hdr *) mptr; + mqinfo ()->mqi_sect = sect; + mqinfo ()->mqi_sectsize = size; + mqinfo ()->mqi_mode = mode; + mqinfo ()->mqi_magic = MQI_MAGIC; + mqinfo ()->mqi_flags = flags; + return mqinfo (); +} + +char * +fhandler_mqueue::get_proc_fd_name (char *buf) +{ + return strcpy (buf, get_name ()); +} + +int __reg2 +fhandler_mqueue::fstat (struct stat *buf) +{ + int ret = fhandler_base::fstat (buf); + if (!ret) + { + buf->st_mode = S_IFREG | mqinfo ()->mqi_mode; + buf->st_dev = FH_MQUEUE; + buf->st_ino = hash_path_name (0, get_name ()); + } + return ret; +} + +int +fhandler_mqueue::dup (fhandler_base *child, int flags) +{ + /* FIXME */ + set_errno (EBADF); + return -1; +} + +void +fhandler_mqueue::fixup_after_fork (HANDLE parent) +{ + __try + { + PVOID mptr = NULL; + SIZE_T filesize = mqinfo ()->mqi_sectsize; + NTSTATUS status; + + DuplicateHandle (parent, mqinfo ()->mqi_sect, + GetCurrentProcess (), &mqinfo ()->mqi_sect, + 0, FALSE, DUPLICATE_SAME_ACCESS); + status = NtMapViewOfSection (mqinfo ()->mqi_sect, NtCurrentProcess (), + &mptr, 0, filesize, NULL, &filesize, + ViewShare, 0, PAGE_READWRITE); + if (!NT_SUCCESS (status)) + api_fatal ("Mapping message queue failed in fork\n"); + else + mqinfo ()->mqi_hdr = (struct mq_hdr *) mptr; + DuplicateHandle (parent, mqinfo ()->mqi_waitsend, + GetCurrentProcess (), &mqinfo ()->mqi_waitsend, + 0, FALSE, DUPLICATE_SAME_ACCESS); + DuplicateHandle (parent, mqinfo ()->mqi_waitrecv, + GetCurrentProcess (), &mqinfo ()->mqi_waitrecv, + 0, FALSE, DUPLICATE_SAME_ACCESS); + DuplicateHandle (parent, mqinfo ()->mqi_lock, + GetCurrentProcess (), &mqinfo ()->mqi_lock, + 0, FALSE, DUPLICATE_SAME_ACCESS); + } + __except (EFAULT) {} + __endtry +} + +int +fhandler_mqueue::close () +{ + int ret = -1; + + __try + { + mqinfo ()->mqi_magic = 0; /* just in case */ + NtUnmapViewOfSection (NtCurrentProcess (), mqinfo ()->mqi_hdr); + NtClose (mqinfo ()->mqi_sect); + NtClose (mqinfo ()->mqi_waitsend); + NtClose (mqinfo ()->mqi_waitrecv); + NtClose (mqinfo ()->mqi_lock); + ret = 0; + } + __except (EFAULT) {} + __endtry + return ret; +} diff --git a/winsup/cygwin/mqueue_types.h b/winsup/cygwin/mqueue_types.h new file mode 100644 index 000000000..eab372238 --- /dev/null +++ b/winsup/cygwin/mqueue_types.h @@ -0,0 +1,58 @@ +/* mqueue_types.h: internal POSIX message queue types + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#pragma once + +#define MQI_MAGIC 0x98765432UL + +/* The mq_attr structure is defined using long datatypes per POSIX. + The mq_fattr is the in-file representation of the mq_attr struct. + Originally created this way for 32/64 bit interoperability, this + is of no concern anymore. */ +#pragma pack (push, 4) +struct mq_fattr +{ + uint32_t mq_flags; + uint32_t mq_maxmsg; + uint32_t mq_msgsize; + uint32_t mq_curmsgs; +}; + +struct mq_hdr +{ + struct mq_fattr mqh_attr; /* the queue's attributes */ + int32_t mqh_head; /* index of first message */ + int32_t mqh_free; /* index of first free message */ + int32_t mqh_nwait; /* #threads blocked in mq_receive() */ + pid_t mqh_pid; /* nonzero PID if mqh_event set */ + char mqh_uname[36]; /* unique name used to identify synchronization + objects connected to this queue */ + union { + struct sigevent mqh_event; /* for mq_notify() */ + uint64_t __mqh_dummy[4]; + }; + uint64_t __mgh_ext[4]; /* Free for extensions. */ + uint32_t mqh_magic; /* Expect MQI_MAGIC here, otherwise it's + an old-style message queue. */ +}; +#pragma pack (pop) + +struct mq_info +{ + struct mq_hdr *mqi_hdr; /* start of mmap'ed region */ + HANDLE mqi_sect; /* file mapping section handle */ + SIZE_T mqi_sectsize; /* file mapping section size */ + mode_t mqi_mode; /* st_mode of the mapped file */ + HANDLE mqi_lock; /* mutex lock */ + HANDLE mqi_waitsend; /* and condition variable for full queue */ + HANDLE mqi_waitrecv; /* and condition variable for empty queue */ + uint32_t mqi_magic; /* magic number if open */ + int mqi_flags; /* flags for this process */ +}; + + diff --git a/winsup/cygwin/posix_ipc.cc b/winsup/cygwin/posix_ipc.cc index 6b8c57fa0..e239ca4c7 100644 --- a/winsup/cygwin/posix_ipc.cc +++ b/winsup/cygwin/posix_ipc.cc @@ -16,6 +16,7 @@ details. */ #include "cygheap.h" #include "sigproc.h" #include "ntdll.h" +#include #include #include #include @@ -103,8 +104,7 @@ ipc_mutex_init (HANDLE *pmtx, const char *name) __small_swprintf (buf, L"mqueue/mtx_%s", name); RtlInitUnicodeString (&uname, buf); - InitializeObjectAttributes (&attr, &uname, - OBJ_INHERIT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE, + InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE, get_shared_parent_dir (), everyone_sd (CYG_MUTANT_ACCESS)); status = NtCreateMutant (pmtx, CYG_MUTANT_ACCESS, &attr, FALSE); @@ -140,12 +140,6 @@ ipc_mutex_unlock (HANDLE mtx) return ReleaseMutex (mtx) ? 0 : geterrno_from_win_error (); } -static inline int -ipc_mutex_close (HANDLE mtx) -{ - return CloseHandle (mtx) ? 0 : geterrno_from_win_error (); -} - static int ipc_cond_init (HANDLE *pevt, const char *name, char sr) { @@ -156,8 +150,7 @@ ipc_cond_init (HANDLE *pevt, const char *name, char sr) __small_swprintf (buf, L"mqueue/evt_%s%c", name, sr); RtlInitUnicodeString (&uname, buf); - InitializeObjectAttributes (&attr, &uname, - OBJ_INHERIT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE, + InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE, get_shared_parent_dir (), everyone_sd (CYG_EVENT_ACCESS)); status = NtCreateEvent (pevt, CYG_EVENT_ACCESS, &attr, @@ -275,12 +268,6 @@ ipc_cond_signal (HANDLE evt) SetEvent (evt); } -static inline void -ipc_cond_close (HANDLE evt) -{ - CloseHandle (evt); -} - class ipc_flock { struct flock fl; @@ -347,40 +334,7 @@ shm_unlink (const char *name) files are created under /dev/mqueue. mq_timedsend and mq_timedreceive are implemented additionally. */ -/* The mq_attr structure is defined using long datatypes per POSIX. - For interoperability reasons between 32 and 64 bit processes, we have - to make sure to use a unified structure layout in the message queue file. - That's what the mq_fattr is, the in-file representation of the mq_attr - struct. */ #pragma pack (push, 4) -struct mq_fattr -{ - uint32_t mq_flags; - uint32_t mq_maxmsg; - uint32_t mq_msgsize; - uint32_t mq_curmsgs; -}; - -struct mq_hdr -{ - struct mq_fattr mqh_attr; /* the queue's attributes */ - int32_t mqh_head; /* index of first message */ - int32_t mqh_free; /* index of first free message */ - int32_t mqh_nwait; /* #threads blocked in mq_receive() */ - pid_t mqh_pid; /* nonzero PID if mqh_event set */ - char mqh_uname[36]; /* unique name used to identify synchronization - objects connected to this queue */ - union { - struct sigevent mqh_event; /* for mq_notify() */ - /* Make sure sigevent takes the same space on 32 and 64 bit systems. - Other than that, it doesn't need to be compatible since only - one process can be notified at a time. */ - uint64_t mqh_placeholder[8]; - }; - uint32_t mqh_magic; /* Expect MQI_MAGIC here, otherwise it's - an old-style message queue. */ -}; - struct msg_hdr { int32_t msg_next; /* index of next on linked list */ @@ -389,18 +343,6 @@ struct msg_hdr }; #pragma pack (pop) -struct mq_info -{ - struct mq_hdr *mqi_hdr; /* start of mmap'ed region */ - uint32_t mqi_magic; /* magic number if open */ - int mqi_flags; /* flags for this process */ - HANDLE mqi_lock; /* mutex lock */ - HANDLE mqi_waitsend; /* and condition variable for full queue */ - HANDLE mqi_waitrecv; /* and condition variable for empty queue */ -}; - -#define MQI_MAGIC 0x98765432UL - #define MSGSIZE(i) roundup((i), sizeof(long)) #define MAX_TRIES 10 /* for waiting for initialization */ @@ -422,19 +364,48 @@ _mq_ipc_init (struct mq_info *mqinfo, const char *name) ret = ipc_cond_init (&mqinfo->mqi_waitsend, name, 'S'); if (ret) { - ipc_mutex_close (mqinfo->mqi_lock); + NtClose (mqinfo->mqi_lock); return ret; } ret = ipc_cond_init (&mqinfo->mqi_waitrecv, name, 'R'); if (ret) { - ipc_cond_close (mqinfo->mqi_waitsend); - ipc_mutex_close (mqinfo->mqi_lock); + NtClose (mqinfo->mqi_waitsend); + NtClose (mqinfo->mqi_lock); return ret; } return 0; } +static int8_t * +_map_file (int fd, SIZE_T filesize, HANDLE §h) +{ + OBJECT_ATTRIBUTES oa; + LARGE_INTEGER fsiz = { QuadPart: (LONGLONG) filesize }; + NTSTATUS status; + PVOID addr = NULL; + + secth = NULL; + InitializeObjectAttributes (&oa, NULL, 0, NULL, NULL); + status = NtCreateSection (§h, SECTION_ALL_ACCESS, &oa, &fsiz, + PAGE_READWRITE, SEC_COMMIT, + (HANDLE) _get_osfhandle (fd)); + if (NT_SUCCESS (status)) + { + status = NtMapViewOfSection (secth, NtCurrentProcess (), &addr, 0, + filesize, NULL, &filesize, + ViewShare, 0, PAGE_READWRITE); + if (!NT_SUCCESS (status)) + { + NtClose (secth); + secth = NULL; + } + } + if (!NT_SUCCESS (status)) + __seterrno_from_nt_status (status); + return (int8_t *) addr; +} + extern "C" mqd_t mq_open (const char *name, int oflag, ...) { @@ -443,7 +414,9 @@ mq_open (const char *name, int oflag, ...) off_t filesize = 0; va_list ap; mode_t mode; - int8_t *mptr = (int8_t *) MAP_FAILED; + HANDLE secth; + int8_t *mptr = NULL; + fhandler_mqueue *fh; struct stat statbuff; struct mq_hdr *mqhdr; struct msg_hdr *msghdr; @@ -502,22 +475,33 @@ mq_open (const char *name, int oflag, ...) __leave; /* Memory map the file */ - mptr = (int8_t *) mmap64 (NULL, (size_t) filesize, - PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (mptr == (int8_t *) MAP_FAILED) + mptr = _map_file (fd, filesize, secth); + if (!mptr) __leave; - /* Allocate one mq_info{} for the queue */ - if (!(mqinfo = (struct mq_info *) - calloc (1, sizeof (struct mq_info)))) + /* Create file descriptor for mqueue */ + cygheap_fdnew fdm; + + if (fdm < 0) __leave; - mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr; - mqinfo->mqi_magic = MQI_MAGIC; - mqinfo->mqi_flags = nonblock; + fh = (fhandler_mqueue *) build_fh_dev (*mqueue_dev); + if (!fh) + __leave; + fdm = fh; + + mqinfo = fh->mqinfo (name, mptr, secth, filesize, mode, nonblock); + + /* Initialize mutex & condition variables */ + i = _mq_ipc_init (mqinfo, mqhdr->mqh_uname); + if (i != 0) + { + set_errno (i); + __leave; + } /* Initialize header at beginning of file */ /* Create free list with all messages on it */ + mqhdr = mqinfo->mqi_hdr; mqhdr->mqh_attr.mq_flags = 0; mqhdr->mqh_attr.mq_maxmsg = attr->mq_maxmsg; mqhdr->mqh_attr.mq_msgsize = attr->mq_msgsize; @@ -526,7 +510,7 @@ mq_open (const char *name, int oflag, ...) mqhdr->mqh_pid = 0; NtAllocateLocallyUniqueId (&luid); __small_sprintf (mqhdr->mqh_uname, "%016X%08x%08x", - hash_path_name (0,mqname), + hash_path_name (0, mqname), luid.HighPart, luid.LowPart); mqhdr->mqh_head = 0; mqhdr->mqh_magic = MQI_MAGIC; @@ -541,18 +525,11 @@ mq_open (const char *name, int oflag, ...) msghdr = (struct msg_hdr *) &mptr[index]; msghdr->msg_next = 0; /* end of free list */ - /* Initialize mutex & condition variables */ - i = _mq_ipc_init (mqinfo, mqhdr->mqh_uname); - if (i != 0) - { - set_errno (i); - __leave; - } /* Initialization complete, turn off user-execute bit */ if (fchmod (fd, mode) == -1) __leave; close (fd); - return ((mqd_t) mqinfo); + return (mqd_t) fdm; } exists: @@ -587,17 +564,14 @@ mq_open (const char *name, int oflag, ...) } filesize = statbuff.st_size; - mptr = (int8_t *) mmap64 (NULL, (size_t) filesize, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (mptr == (int8_t *) MAP_FAILED) + mptr = _map_file (fd, filesize, secth); + if (!mptr) __leave; + close (fd); fd = -1; - /* Allocate one mq_info{} for each open */ - if (!(mqinfo = (struct mq_info *) calloc (1, sizeof (struct mq_info)))) - __leave; - mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr; + mqhdr = (struct mq_hdr *) mptr; if (mqhdr->mqh_magic != MQI_MAGIC) { system_printf ( @@ -607,8 +581,19 @@ mq_open (const char *name, int oflag, ...) set_errno (EACCES); __leave; } - mqinfo->mqi_magic = MQI_MAGIC; - mqinfo->mqi_flags = nonblock; + + /* Create file descriptor for mqueue */ + cygheap_fdnew fdm; + + if (fdm < 0) + __leave; + fh = (fhandler_mqueue *) build_fh_dev (*mqueue_dev); + if (!fh) + __leave; + fdm = fh; + + mqinfo = fh->mqinfo (name, mptr, secth, filesize, statbuff.st_mode, + nonblock); /* Initialize mutex & condition variable */ i = _mq_ipc_init (mqinfo, mqhdr->mqh_uname); @@ -617,7 +602,8 @@ mq_open (const char *name, int oflag, ...) set_errno (i); __leave; } - return (mqd_t) mqinfo; + + return (mqd_t) fdm; } __except (EFAULT) {} __endtry @@ -625,23 +611,39 @@ mq_open (const char *name, int oflag, ...) save_errno save; if (created) unlink (mqname); - if (mptr != (int8_t *) MAP_FAILED) - munmap((void *) mptr, (size_t) filesize); + if (mptr) + { + NtUnmapViewOfSection (NtCurrentProcess (), mptr); + NtClose (secth); + } if (mqinfo) { if (mqinfo->mqi_lock) - ipc_mutex_close (mqinfo->mqi_lock); + NtClose (mqinfo->mqi_lock); if (mqinfo->mqi_waitsend) - ipc_cond_close (mqinfo->mqi_waitsend); + NtClose (mqinfo->mqi_waitsend); if (mqinfo->mqi_waitrecv) - ipc_cond_close (mqinfo->mqi_waitrecv); - free (mqinfo); + NtClose (mqinfo->mqi_waitrecv); } if (fd >= 0) close (fd); return (mqd_t) -1; } +static struct mq_info * +get_mqinfo (cygheap_fdget &fd) +{ + if (fd >= 0) + { + fhandler_mqueue *fh = fd->is_mqueue (); + if (!fh) + set_errno (EINVAL); + else + return fh->mqinfo (); + } + return NULL; +} + extern "C" int mq_getattr (mqd_t mqd, struct mq_attr *mqstat) { @@ -652,7 +654,8 @@ mq_getattr (mqd_t mqd, struct mq_attr *mqstat) __try { - mqinfo = (struct mq_info *) mqd; + cygheap_fdget fd ((int) mqd, true); + mqinfo = get_mqinfo (fd); if (mqinfo->mqi_magic != MQI_MAGIC) { set_errno (EBADF); @@ -688,7 +691,8 @@ mq_setattr (mqd_t mqd, const struct mq_attr *mqstat, struct mq_attr *omqstat) __try { - mqinfo = (struct mq_info *) mqd; + cygheap_fdget fd ((int) mqd, true); + mqinfo = get_mqinfo (fd); if (mqinfo->mqi_magic != MQI_MAGIC) { set_errno (EBADF); @@ -733,7 +737,8 @@ mq_notify (mqd_t mqd, const struct sigevent *notification) __try { - mqinfo = (struct mq_info *) mqd; + cygheap_fdget fd ((int) mqd, true); + mqinfo = get_mqinfo (fd); if (mqinfo->mqi_magic != MQI_MAGIC) { set_errno (EBADF); @@ -793,7 +798,8 @@ _mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio, __try { - mqinfo = (struct mq_info *) mqd; + cygheap_fdget fd ((int) mqd); + mqinfo = get_mqinfo (fd); if (mqinfo->mqi_magic != MQI_MAGIC) { set_errno (EBADF); @@ -920,13 +926,15 @@ _mq_receive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop, struct mq_hdr *mqhdr; struct mq_fattr *attr; struct msg_hdr *msghdr; - struct mq_info *mqinfo = (struct mq_info *) mqd; + struct mq_info *mqinfo; bool ipc_mutex_locked = false; pthread_testcancel (); __try { + cygheap_fdget fd ((int) mqd); + mqinfo = get_mqinfo (fd); if (mqinfo->mqi_magic != MQI_MAGIC) { set_errno (EBADF); @@ -1010,36 +1018,24 @@ mq_timedreceive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop, extern "C" int mq_close (mqd_t mqd) { - long msgsize, filesize; - struct mq_hdr *mqhdr; - struct mq_fattr *attr; struct mq_info *mqinfo; __try { - mqinfo = (struct mq_info *) mqd; + cygheap_fdget fd ((int) mqd, true); + mqinfo = get_mqinfo (fd); if (mqinfo->mqi_magic != MQI_MAGIC) { set_errno (EBADF); __leave; } - mqhdr = mqinfo->mqi_hdr; - attr = &mqhdr->mqh_attr; if (mq_notify (mqd, NULL)) /* unregister calling process */ __leave; - msgsize = MSGSIZE (attr->mq_msgsize); - filesize = sizeof (struct mq_hdr) - + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize)); - if (munmap (mqinfo->mqi_hdr, filesize) == -1) - __leave; - - mqinfo->mqi_magic = 0; /* just in case */ - ipc_cond_close (mqinfo->mqi_waitsend); - ipc_cond_close (mqinfo->mqi_waitrecv); - ipc_mutex_close (mqinfo->mqi_lock); - free (mqinfo); + fd->isclosed (true); + fd->close (); + fd.release (); return 0; } __except (EBADF) {}