public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: POSIX msg queues: Convert mqd_t to a descriptor
@ 2021-05-21 13:33 Corinna Vinschen
  0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2021-05-21 13:33 UTC (permalink / raw)
  To: cygwin-cvs

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=4fc922b2c8a5920304e3aca2f575de9627fa20a1

commit 4fc922b2c8a5920304e3aca2f575de9627fa20a1
Author: Corinna Vinschen <corinna@vinschen.de>
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 <corinna@vinschen.de>

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 <cygwin/_socketflags.h>
 #include <cygwin/_ucred.h>
 #include <sys/un.h>
@@ -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<fhandler_mqueue *> (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 <io.h>
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <stdlib.h>
@@ -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 &secth)
+{
+  OBJECT_ATTRIBUTES oa;
+  LARGE_INTEGER fsiz = { QuadPart: (LONGLONG) filesize };
+  NTSTATUS status;
+  PVOID addr = NULL;
+
+  secth = NULL;
+  InitializeObjectAttributes (&oa, NULL, 0, NULL, NULL);
+  status = NtCreateSection (&secth, 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) {}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-05-21 13:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-21 13:33 [newlib-cygwin] Cygwin: POSIX msg queues: Convert mqd_t to a descriptor Corinna Vinschen

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).