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>
This commit is contained in:
Corinna Vinschen 2021-05-21 12:01:56 +02:00
parent c0949782b7
commit 4fc922b2c8
9 changed files with 343 additions and 122 deletions

View File

@ -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 \

View File

@ -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};

View File

@ -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;

View File

@ -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};

View File

@ -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 ())
{

View File

@ -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

View File

@ -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;
}

View File

@ -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 */
};

View File

@ -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) {}