mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-24 17:47:46 +08:00
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>
114 lines
2.8 KiB
C++
114 lines
2.8 KiB
C++
/* 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;
|
|
}
|