]> sourceware.org Git - newlib-cygwin.git/blobdiff - winsup/cygwin/posix_ipc.cc
Cygwin: POSIX msg queues: implement open/mq_open entirely in fhandler
[newlib-cygwin.git] / winsup / cygwin / posix_ipc.cc
index be4a973a9e4e7222c00464d87c3efcae71839ffa..772072d938ad71d4b2d03b861fa531ecff1b4508 100644 (file)
@@ -1,7 +1,5 @@
 /* posix_ipc.cc: POSIX IPC API for Cygwin.
 
-   Copyright 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
-
 This file is part of Cygwin.
 
 This software is a copyrighted work licensed under the terms of the
@@ -18,6 +16,8 @@ details. */
 #include "cygheap.h"
 #include "sigproc.h"
 #include "ntdll.h"
+#include "tls_pbuf.h"
+#include <io.h>
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <stdlib.h>
@@ -25,7 +25,7 @@ details. */
 #include <mqueue.h>
 #include <semaphore.h>
 
-/* The prefix_len is the length of the path prefix ncluding trailing "/"
+/* The prefix_len is the length of the path prefix including trailing "/"
    (or "/sem." for semaphores) as well as the trailing NUL. */
 static struct
 {
@@ -66,22 +66,33 @@ check_path (char *res_name, ipc_type_t type, const char *name, size_t len)
       set_errno (EINVAL);
       return false;
     }
-  /* Name must not be empty, or just be a single slash, or start with more
-     than one slash.  Same for backslash.
-     Apart from handling backslash like slash, the naming rules are identical
+  /* Apart from handling backslash like slash, the naming rules are identical
      to Linux, including the names and requirements for subdirectories, if
      the name contains further slashes. */
-  if (!name || (strchr ("/\\", name[0])
-               && (!name[1] || strchr ("/\\", name[1]))))
+  /* Name must not be empty and has to start with a slash (or backslash) */
+  if (!name || !strchr ("/\\", name[0]))
     {
       debug_printf ("Invalid %s name '%s'", ipc_names[type].description, name);
       set_errno (EINVAL);
       return false;
     }
-  /* Skip leading (back-)slash. */
-  if (strchr ("/\\", name[0]))
-    ++name;
-  if (len > PATH_MAX - ipc_names[type].prefix_len)
+  /* Name must not consist of just a single slash (or backslash) */
+  if (!name[1])
+    {
+      debug_printf ("Invalid %s name '%s'", ipc_names[type].description, name);
+      set_errno (ENOENT);
+      return false;
+    }
+  /* Name must not contain slashes after the leading one */
+  if (strpbrk (name + 1, "/\\"))
+    {
+      debug_printf ("Invalid %s name '%s'", ipc_names[type].description, name);
+      set_errno (EACCES);
+      return false;
+    }
+  /* Length must be less than or equal to NAME_MAX, or NAME_MAX - 4 in
+     case of semaphores, due to the leading "sem." prefix */
+  if (len > NAME_MAX - (type == semaphore ? strlen ("sem.") : 0))
     {
       debug_printf ("%s name '%s' too long", ipc_names[type].description, name);
       set_errno (ENAMETOOLONG);
@@ -89,37 +100,15 @@ check_path (char *res_name, ipc_type_t type, const char *name, size_t len)
     }
   __small_sprintf (res_name, "%s/%s%s", ipc_names[type].prefix,
                                        type == semaphore ? "sem." : "",
-                                       name);
+                                       name + 1);
   return true;
 }
 
 static int
-ipc_mutex_init (HANDLE *pmtx, const char *name)
+ipc_mutex_lock (HANDLE mtx, bool eintr)
 {
-  WCHAR buf[MAX_PATH];
-  UNICODE_STRING uname;
-  OBJECT_ATTRIBUTES attr;
-  NTSTATUS status;
-
-  __small_swprintf (buf, L"mqueue/mtx_%s", name);
-  RtlInitUnicodeString (&uname, buf);
-  InitializeObjectAttributes (&attr, &uname,
-                             OBJ_INHERIT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
-                             get_shared_parent_dir (),
-                             everyone_sd (CYG_MUTANT_ACCESS));
-  status = NtCreateMutant (pmtx, CYG_MUTANT_ACCESS, &attr, FALSE);
-  if (!NT_SUCCESS (status))
-    {
-      debug_printf ("NtCreateMutant: %y", status);
-      return geterrno_from_win_error (RtlNtStatusToDosError (status));
-    }
-  return 0;
-}
-
-static int
-ipc_mutex_lock (HANDLE mtx)
-{
-  switch (cygwait (mtx, cw_infinite, cw_sig_eintr | cw_cancel | cw_cancel_self))
+  switch (cygwait (mtx, cw_infinite, cw_cancel | cw_cancel_self
+                                    | (eintr ? cw_sig_eintr : cw_sig_restart)))
     {
     case WAIT_OBJECT_0:
     case WAIT_ABANDONED_0:
@@ -139,36 +128,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)
-{
-  WCHAR buf[MAX_PATH];
-  UNICODE_STRING uname;
-  OBJECT_ATTRIBUTES attr;
-  NTSTATUS status;
-
-  __small_swprintf (buf, L"mqueue/evt_%s%c", name, sr);
-  RtlInitUnicodeString (&uname, buf);
-  InitializeObjectAttributes (&attr, &uname,
-                             OBJ_INHERIT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
-                             get_shared_parent_dir (),
-                             everyone_sd (CYG_EVENT_ACCESS));
-  status = NtCreateEvent (pevt, CYG_EVENT_ACCESS, &attr,
-                         NotificationEvent, FALSE);
-  if (!NT_SUCCESS (status))
-    {
-      debug_printf ("NtCreateEvent: %y", status);
-      return geterrno_from_win_error (RtlNtStatusToDosError (status));
-    }
-  return 0;
-}
-
 static int
 ipc_cond_timedwait (HANDLE evt, HANDLE mtx, const struct timespec *abstime)
 {
@@ -177,14 +136,12 @@ ipc_cond_timedwait (HANDLE evt, HANDLE mtx, const struct timespec *abstime)
   DWORD timer_idx = 0;
   int ret = 0;
 
-  set_signal_arrived here (w4[1]);
+  wait_signal_arrived here (w4[1]);
   if ((w4[cnt] = pthread::get_cancel_event ()) != NULL)
     ++cnt;
   if (abstime)
     {
-      if (abstime->tv_sec < 0
-              || abstime->tv_nsec < 0
-              || abstime->tv_nsec > 999999999)
+      if (!valid_timespec (*abstime))
        return EINVAL;
 
       /* If a timeout is set, we create a waitable timer to wait for.
@@ -224,7 +181,7 @@ restart1:
     case WAIT_OBJECT_0 + 2:
       if (timer_idx != 2)
        pthread::static_cancel_self ();
-      /*FALLTHRU*/
+      fallthrough;
     case WAIT_OBJECT_0 + 3:
       ret = ETIMEDOUT;
       break;
@@ -252,7 +209,7 @@ restart1:
        case WAIT_OBJECT_0 + 2:
          if (timer_idx != 2)
            pthread_testcancel ();
-         /*FALLTHRU*/
+         fallthrough;
        case WAIT_OBJECT_0 + 3:
          ret = ETIMEDOUT;
          break;
@@ -276,12 +233,6 @@ ipc_cond_signal (HANDLE evt)
   SetEvent (evt);
 }
 
-static inline void
-ipc_cond_close (HANDLE evt)
-{
-  CloseHandle (evt);
-}
-
 class ipc_flock
 {
   struct flock fl;
@@ -348,84 +299,13 @@ 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 */
-  int32_t         msg_len;      /* actual length */
-  unsigned int    msg_prio;     /* priority */
-};
-#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 */
-
-struct mq_attr defattr = { 0, 10, 8192, 0 };   /* Linux defaults. */
-
-extern "C" off_t lseek64 (int, off_t, int);
-extern "C" void *mmap64 (void *, size_t, int, int, int, off_t);
-
 extern "C" mqd_t
 mq_open (const char *name, int oflag, ...)
 {
-  int i, fd = -1, nonblock, created;
-  long msgsize, index;
-  off_t filesize = 0;
   va_list ap;
-  mode_t mode;
-  int8_t *mptr;
-  struct stat statbuff;
-  struct mq_hdr *mqhdr;
-  struct msg_hdr *msghdr;
-  struct mq_attr *attr;
-  struct mq_info *mqinfo;
-  LUID luid;
+  mode_t mode = 0;
+  fhandler_mqueue *fh = NULL;
+  struct mq_attr *attr = NULL;
 
   size_t len = strlen (name);
   char mqname[ipc_names[mqueue].prefix_len + len];
@@ -433,207 +313,52 @@ mq_open (const char *name, int oflag, ...)
   if (!check_path (mqname, mqueue, name, len))
     return (mqd_t) -1;
 
-  myfault efault;
-  if (efault.faulted (EFAULT))
-    return (mqd_t) -1;
-
-  oflag &= (O_CREAT | O_EXCL | O_NONBLOCK);
-  created = 0;
-  nonblock = oflag & O_NONBLOCK;
-  oflag &= ~O_NONBLOCK;
-  mptr = (int8_t *) MAP_FAILED;
-  mqinfo = NULL;
-
-again:
-  if (oflag & O_CREAT)
+  __try
     {
-      va_start (ap, oflag);            /* init ap to final named argument */
-      mode = va_arg (ap, mode_t) & ~S_IXUSR;
-      attr = va_arg (ap, struct mq_attr *);
-      va_end (ap);
-
-      /* Open and specify O_EXCL and user-execute */
-      fd = open (mqname, oflag | O_EXCL | O_RDWR | O_CLOEXEC, mode | S_IXUSR);
-      if (fd < 0)
-       {
-         if (errno == EEXIST && (oflag & O_EXCL) == 0)
-           goto exists;                /* already exists, OK */
-         return (mqd_t) -1;
-       }
-      created = 1;
-      /* First one to create the file initializes it */
-      if (attr == NULL)
-       attr = &defattr;
-      /* Check minimum and maximum values.  The max values are pretty much
-         arbitrary, taken from the linux mq_overview man page.  However,
-        these max values make sure that the internal mq_fattr structure
-        can use 32 bit types. */
-      else if (attr->mq_maxmsg <= 0 || attr->mq_maxmsg > 32768
-              || attr->mq_msgsize <= 0 || attr->mq_msgsize > 1048576)
-       {
-         set_errno (EINVAL);
-         goto err;
-       }
-      /* Calculate and set the file size */
-      msgsize = MSGSIZE (attr->mq_msgsize);
-      filesize = sizeof (struct mq_hdr)
-                + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
-      if (lseek64 (fd, filesize - 1, SEEK_SET) == -1)
-       goto err;
-      if (write (fd, "", 1) == -1)
-       goto err;
-
-      /* 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)
-       goto err;
-
-      /* Allocate one mq_info{} for the queue */
-      if (!(mqinfo = (struct mq_info *) calloc (1, sizeof (struct mq_info))))
-       goto err;
-      mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr;
-      mqinfo->mqi_magic = MQI_MAGIC;
-      mqinfo->mqi_flags = nonblock;
-
-      /* Initialize header at beginning of file */
-      /* Create free list with all messages on it */
-      mqhdr->mqh_attr.mq_flags = 0;
-      mqhdr->mqh_attr.mq_maxmsg = attr->mq_maxmsg;
-      mqhdr->mqh_attr.mq_msgsize = attr->mq_msgsize;
-      mqhdr->mqh_attr.mq_curmsgs = 0;
-      mqhdr->mqh_nwait = 0;
-      mqhdr->mqh_pid = 0;
-      NtAllocateLocallyUniqueId (&luid);
-      __small_sprintf (mqhdr->mqh_uname, "%016X%08x%08x",
-                      hash_path_name (0,mqname),
-                      luid.HighPart, luid.LowPart);
-      mqhdr->mqh_head = 0;
-      mqhdr->mqh_magic = MQI_MAGIC;
-      index = sizeof (struct mq_hdr);
-      mqhdr->mqh_free = index;
-      for (i = 0; i < attr->mq_maxmsg - 1; i++)
+      if (oflag & O_CREAT)
        {
-         msghdr = (struct msg_hdr *) &mptr[index];
-         index += sizeof (struct msg_hdr) + msgsize;
-         msghdr->msg_next = index;
+         va_start (ap, oflag);         /* init ap to final named argument */
+         mode = va_arg (ap, mode_t) & ~S_IXUSR;
+         attr = va_arg (ap, struct mq_attr *);
+         va_end (ap);
        }
-      msghdr = (struct msg_hdr *) &mptr[index];
-      msghdr->msg_next = 0;            /* end of free list */
-
-      /* Initialize mutex & condition variables */
-      i = ipc_mutex_init (&mqinfo->mqi_lock, mqhdr->mqh_uname);
-      if (i != 0)
-       goto pthreaderr;
-
-      i = ipc_cond_init (&mqinfo->mqi_waitsend, mqhdr->mqh_uname, 'S');
-      if (i != 0)
-       goto pthreaderr;
-
-      i = ipc_cond_init (&mqinfo->mqi_waitrecv, mqhdr->mqh_uname, 'R');
-      if (i != 0)
-       goto pthreaderr;
-
-      /* Initialization complete, turn off user-execute bit */
-      if (fchmod (fd, mode) == -1)
-       goto err;
-      close (fd);
-      return ((mqd_t) mqinfo);
-    }
 
-exists:
-  /* Open the file then memory map */
-  if ((fd = open (mqname, O_RDWR | O_CLOEXEC)) < 0)
-    {
-      if (errno == ENOENT && (oflag & O_CREAT))
-       goto again;
-      goto err;
-    }
-  /* Make certain initialization is complete */
-  for (i = 0; i < MAX_TRIES; i++)
-    {
-      if (stat64 (mqname, &statbuff) == -1)
+      /* Create file descriptor for mqueue */
+      cygheap_fdnew fd;
+
+      if (fd < 0)
+       __leave;
+      fh = (fhandler_mqueue *) build_fh_name (mqname,
+                                             PC_OPEN | PC_POSIX
+                                             | PC_SYM_NOFOLLOW | PC_NULLEMPTY,
+                                             NULL);
+      if (!fh)
+       __leave;
+
+      if (fh->mq_open (oflag, mode, attr))
        {
-         if (errno == ENOENT && (oflag & O_CREAT))
-           {
-             close (fd);
-             fd = -1;
-             goto again;
-           }
-         goto err;
+         fd = fh;
+         return (mqd_t) fd;
        }
-      if ((statbuff.st_mode & S_IXUSR) == 0)
-       break;
-      sleep (1);
-    }
-  if (i == MAX_TRIES)
-    {
-      set_errno (ETIMEDOUT);
-      goto err;
-    }
-
-  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)
-    goto err;
-  close (fd);
-  fd = -1;
-
-  /* Allocate one mq_info{} for each open */
-  if (!(mqinfo = (struct mq_info *) calloc (1, sizeof (struct mq_info))))
-    goto err;
-  mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr;
-  if (mqhdr->mqh_magic != MQI_MAGIC)
-    {
-      system_printf (
-"Old message queue \"%s\" detected!\n"
-"This file is not usable as message queue anymore due to changes in the "
-"internal file layout.  Please remove the file and try again.", mqname);
-      set_errno (EACCES);
-      goto err;
     }
-  mqinfo->mqi_magic = MQI_MAGIC;
-  mqinfo->mqi_flags = nonblock;
-
-  /* Initialize mutex & condition variable */
-  i = ipc_mutex_init (&mqinfo->mqi_lock, mqhdr->mqh_uname);
-  if (i != 0)
-    goto pthreaderr;
-
-  i = ipc_cond_init (&mqinfo->mqi_waitsend, mqhdr->mqh_uname, 'S');
-  if (i != 0)
-    goto pthreaderr;
-
-  i = ipc_cond_init (&mqinfo->mqi_waitrecv, mqhdr->mqh_uname, 'R');
-  if (i != 0)
-    goto pthreaderr;
-
-  return (mqd_t) mqinfo;
-
-pthreaderr:
-  errno = i;
-err:
-  /* Don't let following function calls change errno */
-  save_errno save;
+  __except (EFAULT) {}
+  __endtry
+  if (fh)
+    delete fh;
+  return (mqd_t) -1;
+}
 
-  if (created)
-    unlink (mqname);
-  if (mptr != (int8_t *) MAP_FAILED)
-    munmap((void *) mptr, (size_t) filesize);
-  if (mqinfo)
+static struct mq_info *
+get_mqinfo (cygheap_fdget &fd)
+{
+  if (fd >= 0)
     {
-      if (mqinfo->mqi_lock)
-       ipc_mutex_close (mqinfo->mqi_lock);
-      if (mqinfo->mqi_waitsend)
-       ipc_cond_close (mqinfo->mqi_waitsend);
-      if (mqinfo->mqi_waitrecv)
-       ipc_cond_close (mqinfo->mqi_waitrecv);
-      free (mqinfo);
+      fhandler_mqueue *fh = fd->is_mqueue ();
+      if (fh)
+       return fh->mqinfo ();
+      set_errno (EINVAL);
     }
-  if (fd >= 0)
-    close (fd);
-  return (mqd_t) -1;
+  return NULL;
 }
 
 extern "C" int
@@ -644,30 +369,33 @@ mq_getattr (mqd_t mqd, struct mq_attr *mqstat)
   struct mq_fattr *attr;
   struct mq_info *mqinfo;
 
-  myfault efault;
-  if (efault.faulted (EBADF))
-      return -1;
-
-  mqinfo = (struct mq_info *) mqd;
-  if (mqinfo->mqi_magic != MQI_MAGIC)
-    {
-      set_errno (EBADF);
-      return -1;
-    }
-  mqhdr = mqinfo->mqi_hdr;
-  attr = &mqhdr->mqh_attr;
-  if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
+  __try
     {
-      errno = n;
-      return -1;
-    }
-  mqstat->mq_flags = mqinfo->mqi_flags;   /* per-open */
-  mqstat->mq_maxmsg = attr->mq_maxmsg;    /* remaining three per-queue */
-  mqstat->mq_msgsize = attr->mq_msgsize;
-  mqstat->mq_curmsgs = attr->mq_curmsgs;
+      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 ((n = ipc_mutex_lock (mqinfo->mqi_lock, false)) != 0)
+       {
+         errno = n;
+         __leave;
+       }
+      mqstat->mq_flags = mqinfo->mqi_flags;   /* per-open */
+      mqstat->mq_maxmsg = attr->mq_maxmsg;    /* remaining three per-queue */
+      mqstat->mq_msgsize = attr->mq_msgsize;
+      mqstat->mq_curmsgs = attr->mq_curmsgs;
 
-  ipc_mutex_unlock (mqinfo->mqi_lock);
-  return 0;
+      ipc_mutex_unlock (mqinfo->mqi_lock);
+      return 0;
+    }
+  __except (EBADF) {}
+  __endtry
+  return -1;
 }
 
 extern "C" int
@@ -678,39 +406,42 @@ mq_setattr (mqd_t mqd, const struct mq_attr *mqstat, struct mq_attr *omqstat)
   struct mq_fattr *attr;
   struct mq_info *mqinfo;
 
-  myfault efault;
-  if (efault.faulted (EBADF))
-      return -1;
-
-  mqinfo = (struct mq_info *) mqd;
-  if (mqinfo->mqi_magic != MQI_MAGIC)
+  __try
     {
-      set_errno (EBADF);
-      return -1;
-    }
-  mqhdr = mqinfo->mqi_hdr;
-  attr = &mqhdr->mqh_attr;
-  if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
-    {
-      errno = n;
-      return -1;
-    }
+      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 ((n = ipc_mutex_lock (mqinfo->mqi_lock, false)) != 0)
+       {
+         errno = n;
+         __leave;
+       }
 
-  if (omqstat != NULL)
-    {
-      omqstat->mq_flags = mqinfo->mqi_flags;  /* previous attributes */
-      omqstat->mq_maxmsg = attr->mq_maxmsg;
-      omqstat->mq_msgsize = attr->mq_msgsize;
-      omqstat->mq_curmsgs = attr->mq_curmsgs; /* and current status */
-    }
+      if (omqstat != NULL)
+       {
+         omqstat->mq_flags = mqinfo->mqi_flags;  /* previous attributes */
+         omqstat->mq_maxmsg = attr->mq_maxmsg;
+         omqstat->mq_msgsize = attr->mq_msgsize;
+         omqstat->mq_curmsgs = attr->mq_curmsgs; /* and current status */
+       }
 
-  if (mqstat->mq_flags & O_NONBLOCK)
-    mqinfo->mqi_flags |= O_NONBLOCK;
-  else
-    mqinfo->mqi_flags &= ~O_NONBLOCK;
+      if (mqstat->mq_flags & O_NONBLOCK)
+       mqinfo->mqi_flags |= O_NONBLOCK;
+      else
+       mqinfo->mqi_flags &= ~O_NONBLOCK;
 
-  ipc_mutex_unlock (mqinfo->mqi_lock);
-  return 0;
+      ipc_mutex_unlock (mqinfo->mqi_lock);
+      return 0;
+    }
+  __except (EBADF) {}
+  __endtry
+  return -1;
 }
 
 extern "C" int
@@ -721,45 +452,48 @@ mq_notify (mqd_t mqd, const struct sigevent *notification)
   struct mq_hdr *mqhdr;
   struct mq_info *mqinfo;
 
-  myfault efault;
-  if (efault.faulted (EBADF))
-      return -1;
-
-  mqinfo = (struct mq_info *) mqd;
-  if (mqinfo->mqi_magic != MQI_MAGIC)
-    {
-      set_errno (EBADF);
-      return -1;
-    }
-  mqhdr = mqinfo->mqi_hdr;
-  if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
+  __try
     {
-      errno = n;
-      return -1;
-    }
+      cygheap_fdget fd ((int) mqd, true);
+      mqinfo = get_mqinfo (fd);
+      if (mqinfo->mqi_magic != MQI_MAGIC)
+       {
+         set_errno (EBADF);
+         __leave;
+       }
+      mqhdr = mqinfo->mqi_hdr;
+      if ((n = ipc_mutex_lock (mqinfo->mqi_lock, false)) != 0)
+       {
+         errno = n;
+         __leave;
+       }
 
-  pid = getpid ();
-  if (!notification)
-    {
-      if (mqhdr->mqh_pid == pid)
-         mqhdr->mqh_pid = 0;     /* unregister calling process */
-    }
-  else
-    {
-      if (mqhdr->mqh_pid != 0)
+      pid = getpid ();
+      if (!notification)
+       {
+         if (mqhdr->mqh_pid == pid)
+             mqhdr->mqh_pid = 0;     /* unregister calling process */
+       }
+      else
        {
-         if (kill (mqhdr->mqh_pid, 0) != -1 || errno != ESRCH)
+         if (mqhdr->mqh_pid != 0)
            {
-             set_errno (EBUSY);
-             ipc_mutex_unlock (mqinfo->mqi_lock);
-             return -1;
+             if (kill (mqhdr->mqh_pid, 0) != -1 || errno != ESRCH)
+               {
+                 set_errno (EBUSY);
+                 ipc_mutex_unlock (mqinfo->mqi_lock);
+                 __leave;
+               }
            }
+         mqhdr->mqh_pid = pid;
+         mqhdr->mqh_event = *notification;
        }
-      mqhdr->mqh_pid = pid;
-      mqhdr->mqh_event = *notification;
+      ipc_mutex_unlock (mqinfo->mqi_lock);
+      return 0;
     }
-  ipc_mutex_unlock (mqinfo->mqi_lock);
-  return 0;
+  __except (EBADF) {}
+  __endtry
+  return -1;
 }
 
 static int
@@ -773,113 +507,116 @@ _mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
   struct mq_hdr *mqhdr;
   struct mq_fattr *attr;
   struct msg_hdr *msghdr, *nmsghdr, *pmsghdr;
-  struct mq_info *mqinfo;
+  struct mq_info *mqinfo = NULL;
+  bool ipc_mutex_locked = false;
+  int ret = -1;
 
   pthread_testcancel ();
 
-  myfault efault;
-  if (efault.faulted (EBADF))
-      return -1;
-
-  mqinfo = (struct mq_info *) mqd;
-  if (mqinfo->mqi_magic != MQI_MAGIC)
+  __try
     {
-      set_errno (EBADF);
-      return -1;
-    }
-  if (prio > MQ_PRIO_MAX)
-    {
-      set_errno (EINVAL);
-      return -1;
-    }
-
-  mqhdr = mqinfo->mqi_hdr;        /* struct pointer */
-  mptr = (int8_t *) mqhdr;        /* byte pointer */
-  attr = &mqhdr->mqh_attr;
-  if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
-    {
-      errno = n;
-      return -1;
-    }
+      cygheap_fdget fd ((int) mqd);
+      mqinfo = get_mqinfo (fd);
+      if (mqinfo->mqi_magic != MQI_MAGIC)
+       {
+         set_errno (EBADF);
+         __leave;
+       }
+      if (prio >= MQ_PRIO_MAX)
+       {
+         set_errno (EINVAL);
+         __leave;
+       }
 
-  if (len > (size_t) attr->mq_msgsize)
-    {
-      set_errno (EMSGSIZE);
-      goto err;
-    }
-  if (attr->mq_curmsgs == 0)
-    {
-      if (mqhdr->mqh_pid != 0 && mqhdr->mqh_nwait == 0)
+      mqhdr = mqinfo->mqi_hdr;        /* struct pointer */
+      mptr = (int8_t *) mqhdr;        /* byte pointer */
+      attr = &mqhdr->mqh_attr;
+      if ((n = ipc_mutex_lock (mqinfo->mqi_lock, true)) != 0)
        {
-         sigev = &mqhdr->mqh_event;
-         if (sigev->sigev_notify == SIGEV_SIGNAL)
-           sigqueue (mqhdr->mqh_pid, sigev->sigev_signo, sigev->sigev_value);
-         mqhdr->mqh_pid = 0;             /* unregister */
+         errno = n;
+         __leave;
        }
-    }
-  else if (attr->mq_curmsgs >= attr->mq_maxmsg)
-    {
-      /* Queue is full */
-      if (mqinfo->mqi_flags & O_NONBLOCK)
+      ipc_mutex_locked = true;
+      if (len > (size_t) attr->mq_msgsize)
        {
-         set_errno (EAGAIN);
-         goto err;
+         set_errno (EMSGSIZE);
+         __leave;
        }
-      /* Wait for room for one message on the queue */
-      while (attr->mq_curmsgs >= attr->mq_maxmsg)
+      if (attr->mq_curmsgs == 0)
        {
-         int ret = ipc_cond_timedwait (mqinfo->mqi_waitsend, mqinfo->mqi_lock,
-                                       abstime);
-         if (ret != 0)
+         if (mqhdr->mqh_pid != 0 && mqhdr->mqh_nwait == 0)
            {
-             set_errno (ret);
-             return -1;
+             sigev = &mqhdr->mqh_event;
+             if (sigev->sigev_notify == SIGEV_SIGNAL)
+               sigqueue (mqhdr->mqh_pid, sigev->sigev_signo,
+                         sigev->sigev_value);
+             mqhdr->mqh_pid = 0;             /* unregister */
+           }
+       }
+      else if (attr->mq_curmsgs >= attr->mq_maxmsg)
+       {
+         /* Queue is full */
+         if (mqinfo->mqi_flags & O_NONBLOCK)
+           {
+             set_errno (EAGAIN);
+             __leave;
+           }
+         /* Wait for room for one message on the queue */
+         while (attr->mq_curmsgs >= attr->mq_maxmsg)
+           {
+             int ret = ipc_cond_timedwait (mqinfo->mqi_waitsend,
+                                           mqinfo->mqi_lock, abstime);
+             if (ret != 0)
+               {
+                 set_errno (ret);
+                 __leave;
+               }
            }
        }
-    }
 
-  /* nmsghdr will point to new message */
-  if ((freeindex = mqhdr->mqh_free) == 0)
-    api_fatal ("mq_send: curmsgs = %ld; free = 0", attr->mq_curmsgs);
+      /* nmsghdr will point to new message */
+      if ((freeindex = mqhdr->mqh_free) == 0)
+       api_fatal ("mq_send: curmsgs = %ld; free = 0", attr->mq_curmsgs);
 
-  nmsghdr = (struct msg_hdr *) &mptr[freeindex];
-  nmsghdr->msg_prio = prio;
-  nmsghdr->msg_len = len;
-  memcpy (nmsghdr + 1, ptr, len);          /* copy message from caller */
-  mqhdr->mqh_free = nmsghdr->msg_next;    /* new freelist head */
+      nmsghdr = (struct msg_hdr *) &mptr[freeindex];
+      nmsghdr->msg_prio = prio;
+      nmsghdr->msg_len = len;
+      memcpy (nmsghdr + 1, ptr, len);         /* copy message from caller */
+      mqhdr->mqh_free = nmsghdr->msg_next;    /* new freelist head */
 
-  /* Find right place for message in linked list */
-  index = mqhdr->mqh_head;
-  pmsghdr = (struct msg_hdr *) &(mqhdr->mqh_head);
-  while (index)
-    {
-      msghdr = (struct msg_hdr *) &mptr[index];
-      if (prio > msghdr->msg_prio)
+      /* Find right place for message in linked list */
+      index = mqhdr->mqh_head;
+      pmsghdr = (struct msg_hdr *) &(mqhdr->mqh_head);
+      while (index)
        {
-         nmsghdr->msg_next = index;
+         msghdr = (struct msg_hdr *) &mptr[index];
+         if (prio > msghdr->msg_prio)
+           {
+             nmsghdr->msg_next = index;
+             pmsghdr->msg_next = freeindex;
+             break;
+           }
+         index = msghdr->msg_next;
+         pmsghdr = msghdr;
+       }
+      if (index == 0)
+       {
+         /* Queue was empty or new goes at end of list */
          pmsghdr->msg_next = freeindex;
-         break;
+         nmsghdr->msg_next = 0;
        }
-      index = msghdr->msg_next;
-      pmsghdr = msghdr;
-    }
-  if (index == 0)
-    {
-      /* Queue was empty or new goes at end of list */
-      pmsghdr->msg_next = freeindex;
-      nmsghdr->msg_next = 0;
-    }
-  /* Wake up anyone blocked in mq_receive waiting for a message */
-  if (attr->mq_curmsgs == 0)
-    ipc_cond_signal (mqinfo->mqi_waitrecv);
-  attr->mq_curmsgs++;
+      /* Wake up anyone blocked in mq_receive waiting for a message */
+      if (attr->mq_curmsgs == 0)
+       ipc_cond_signal (mqinfo->mqi_waitrecv);
+      attr->mq_curmsgs++;
 
-  ipc_mutex_unlock (mqinfo->mqi_lock);
-  return 0;
-
-err:
-  ipc_mutex_unlock (mqinfo->mqi_lock);
-  return -1;
+      ret = 0;
+    }
+  __except (EBADF) {}
+  __endtry
+  if (ipc_mutex_locked)
+    ipc_mutex_unlock (mqinfo->mqi_lock);
+  return ret;
 }
 
 extern "C" int
@@ -902,85 +639,84 @@ _mq_receive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop,
   int n;
   long index;
   int8_t *mptr;
-  ssize_t len;
+  ssize_t len = -1;
   struct mq_hdr *mqhdr;
   struct mq_fattr *attr;
   struct msg_hdr *msghdr;
   struct mq_info *mqinfo;
+  bool ipc_mutex_locked = false;
 
   pthread_testcancel ();
 
-  myfault efault;
-  if (efault.faulted (EBADF))
-      return -1;
-
-  mqinfo = (struct mq_info *) mqd;
-  if (mqinfo->mqi_magic != MQI_MAGIC)
-    {
-      set_errno (EBADF);
-      return -1;
-    }
-  mqhdr = mqinfo->mqi_hdr;        /* struct pointer */
-  mptr = (int8_t *) mqhdr;        /* byte pointer */
-  attr = &mqhdr->mqh_attr;
-  if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
-    {
-      errno = n;
-      return -1;
-    }
-
-  if (maxlen < (size_t) attr->mq_msgsize)
-    {
-      set_errno (EMSGSIZE);
-      goto err;
-    }
-  if (attr->mq_curmsgs == 0)   /* queue is empty */
+  __try
     {
-      if (mqinfo->mqi_flags & O_NONBLOCK)
+      cygheap_fdget fd ((int) mqd);
+      mqinfo = get_mqinfo (fd);
+      if (mqinfo->mqi_magic != MQI_MAGIC)
        {
-         set_errno (EAGAIN);
-         goto err;
+         set_errno (EBADF);
+         __leave;
        }
-      /* Wait for a message to be placed onto queue */
-      mqhdr->mqh_nwait++;
-      while (attr->mq_curmsgs == 0)
+      mqhdr = mqinfo->mqi_hdr;        /* struct pointer */
+      mptr = (int8_t *) mqhdr;        /* byte pointer */
+      attr = &mqhdr->mqh_attr;
+      if ((n = ipc_mutex_lock (mqinfo->mqi_lock, true)) != 0)
        {
-         int ret = ipc_cond_timedwait (mqinfo->mqi_waitrecv, mqinfo->mqi_lock,
-                                       abstime);
-         if (ret != 0)
+         errno = n;
+         __leave;
+       }
+      ipc_mutex_locked = true;
+      if (maxlen < (size_t) attr->mq_msgsize)
+       {
+         set_errno (EMSGSIZE);
+         __leave;
+       }
+      if (attr->mq_curmsgs == 0)       /* queue is empty */
+       {
+         if (mqinfo->mqi_flags & O_NONBLOCK)
+           {
+             set_errno (EAGAIN);
+             __leave;
+           }
+         /* Wait for a message to be placed onto queue */
+         mqhdr->mqh_nwait++;
+         while (attr->mq_curmsgs == 0)
            {
-             set_errno (ret);
-             return -1;
+             int ret = ipc_cond_timedwait (mqinfo->mqi_waitrecv,
+                                           mqinfo->mqi_lock, abstime);
+             if (ret != 0)
+               {
+                 set_errno (ret);
+                 __leave;
+               }
            }
+         mqhdr->mqh_nwait--;
        }
-      mqhdr->mqh_nwait--;
-    }
-
-  if ((index = mqhdr->mqh_head) == 0)
-    api_fatal ("mq_receive: curmsgs = %ld; head = 0", attr->mq_curmsgs);
-
-  msghdr = (struct msg_hdr *) &mptr[index];
-  mqhdr->mqh_head = msghdr->msg_next;     /* new head of list */
-  len = msghdr->msg_len;
-  memcpy(ptr, msghdr + 1, len);           /* copy the message itself */
-  if (priop != NULL)
-    *priop = msghdr->msg_prio;
 
-  /* Just-read message goes to front of free list */
-  msghdr->msg_next = mqhdr->mqh_free;
-  mqhdr->mqh_free = index;
+      if ((index = mqhdr->mqh_head) == 0)
+       api_fatal ("mq_receive: curmsgs = %ld; head = 0", attr->mq_curmsgs);
 
-  /* Wake up anyone blocked in mq_send waiting for room */
-  if (attr->mq_curmsgs == attr->mq_maxmsg)
-    ipc_cond_signal (mqinfo->mqi_waitsend);
-  attr->mq_curmsgs--;
+      msghdr = (struct msg_hdr *) &mptr[index];
+      mqhdr->mqh_head = msghdr->msg_next;     /* new head of list */
+      len = msghdr->msg_len;
+      memcpy(ptr, msghdr + 1, len);           /* copy the message itself */
+      if (priop != NULL)
+       *priop = msghdr->msg_prio;
+
+      /* Just-read message goes to front of free list */
+      msghdr->msg_next = mqhdr->mqh_free;
+      mqhdr->mqh_free = index;
 
-  ipc_mutex_unlock (mqinfo->mqi_lock);
+      /* Wake up anyone blocked in mq_send waiting for room */
+      if (attr->mq_curmsgs == attr->mq_maxmsg)
+       ipc_cond_signal (mqinfo->mqi_waitsend);
+      attr->mq_curmsgs--;
+    }
+  __except (EBADF) {}
+  __endtry
+  if (ipc_mutex_locked)
+    ipc_mutex_unlock (mqinfo->mqi_lock);
   return len;
-
-err:
-  ipc_mutex_unlock (mqinfo->mqi_lock);
-  return -1;
 }
 
 extern "C" ssize_t
@@ -999,39 +735,26 @@ 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;
-
-  myfault efault;
-  if (efault.faulted (EBADF))
-      return -1;
-
-  mqinfo = (struct mq_info *) mqd;
-  if (mqinfo->mqi_magic != MQI_MAGIC)
+  __try
     {
-      set_errno (EBADF);
-      return -1;
-    }
-  mqhdr = mqinfo->mqi_hdr;
-  attr = &mqhdr->mqh_attr;
-
-  if (mq_notify (mqd, NULL))   /* unregister calling process */
-    return -1;
+      cygheap_fdget fd ((int) mqd, true);
+      if (!fd->is_mqueue ())
+       {
+         set_errno (EBADF);
+         __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)
-    return -1;
+      if (mq_notify (mqd, NULL))       /* unregister calling process */
+       __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);
-  return 0;
+      fd->isclosed (true);
+      fd->close ();
+      fd.release ();
+      return 0;
+    }
+  __except (EBADF) {}
+  __endtry
+  return -1;
 }
 
 extern "C" int
@@ -1052,6 +775,8 @@ mq_unlink (const char *name)
    the already existing semaphore class in thread.cc.  Using a file backed
    solution allows to implement kernel persistent named semaphores.  */
 
+#define         MAX_TRIES      10      /* for waiting for initialization */
+
 struct sem_finfo
 {
   unsigned int       value;
@@ -1062,7 +787,7 @@ struct sem_finfo
 extern "C" sem_t *
 sem_open (const char *name, int oflag, ...)
 {
-  int i, fd = -1, created;
+  int i, fd = -1, created = 0;
   va_list ap;
   mode_t mode = 0;
   unsigned int value = 0;
@@ -1078,97 +803,99 @@ sem_open (const char *name, int oflag, ...)
   if (!check_path (semname, semaphore, name, len))
     return SEM_FAILED;
 
-  myfault efault;
-  if (efault.faulted (EFAULT))
-    return SEM_FAILED;
-
-  created = 0;
-  oflag &= (O_CREAT | O_EXCL);
-
-again:
-  if (oflag & O_CREAT)
+  __try
     {
-      va_start (ap, oflag);            /* init ap to final named argument */
-      mode = va_arg (ap, mode_t) & ~S_IXUSR;
-      value = va_arg (ap, unsigned int);
-      va_end (ap);
+      oflag &= (O_CREAT | O_EXCL);
 
-      /* Open and specify O_EXCL and user-execute */
-      fd = open (semname, oflag | O_EXCL | O_RDWR | O_CLOEXEC, mode | S_IXUSR);
-      if (fd < 0)
+    again:
+      if (oflag & O_CREAT)
        {
-         if (errno == EEXIST && (oflag & O_EXCL) == 0)
-           goto exists;                /* already exists, OK */
-         return SEM_FAILED;
+         va_start (ap, oflag);         /* init ap to final named argument */
+         mode = va_arg (ap, mode_t) & ~S_IXUSR;
+         value = va_arg (ap, unsigned int);
+         va_end (ap);
+
+         /* Open and specify O_EXCL and user-execute */
+         fd = open (semname, oflag | O_EXCL | O_RDWR | O_CLOEXEC,
+                    mode | S_IXUSR);
+         if (fd < 0)
+           {
+             if (errno == EEXIST && (oflag & O_EXCL) == 0)
+               goto exists;            /* already exists, OK */
+             return SEM_FAILED;
+           }
+         created = 1;
+         /* First one to create the file initializes it. */
+         NtAllocateLocallyUniqueId (&sf.luid);
+         sf.value = value;
+         sf.hash = hash_path_name (0, semname);
+         if (write (fd, &sf, sizeof sf) != sizeof sf)
+           __leave;
+         sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, value,
+                                wasopen);
+         if (sem == SEM_FAILED)
+           __leave;
+         /* Initialization complete, turn off user-execute bit */
+         if (fchmod (fd, mode) == -1)
+           __leave;
+         /* Don't close (fd); */
+         return sem;
        }
-      created = 1;
-      /* First one to create the file initializes it. */
-      NtAllocateLocallyUniqueId (&sf.luid);
-      sf.value = value;
-      sf.hash = hash_path_name (0, semname);
-      if (write (fd, &sf, sizeof sf) != sizeof sf)
-       goto err;
-      sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, value, wasopen);
-      if (sem == SEM_FAILED)
-       goto err;
-      /* Initialization complete, turn off user-execute bit */
-      if (fchmod (fd, mode) == -1)
-       goto err;
-      /* Don't close (fd); */
-      return sem;
-    }
 
-exists:
-  /* Open the file and fetch the semaphore name. */
-  if ((fd = open (semname, O_RDWR | O_CLOEXEC)) < 0)
-    {
-      if (errno == ENOENT && (oflag & O_CREAT))
-       goto again;
-      goto err;
-    }
-  /* Make certain initialization is complete */
-  for (i = 0; i < MAX_TRIES; i++)
-    {
-      if (stat64 (semname, &statbuff) == -1)
+    exists:
+      /* Open the file and fetch the semaphore name. */
+      if ((fd = open (semname, O_RDWR | O_CLOEXEC)) < 0)
        {
          if (errno == ENOENT && (oflag & O_CREAT))
+           goto again;
+         __leave;
+       }
+      /* Make certain initialization is complete */
+      for (i = 0; i < MAX_TRIES; i++)
+       {
+         if (stat64 (semname, &statbuff) == -1)
            {
-             close (fd);
-             fd = -1;
-             goto again;
+             if (errno == ENOENT && (oflag & O_CREAT))
+               {
+                 close (fd);
+                 fd = -1;
+                 goto again;
+               }
+             __leave;
            }
-         goto err;
+         if ((statbuff.st_mode & S_IXUSR) == 0)
+           break;
+         sleep (1);
        }
-      if ((statbuff.st_mode & S_IXUSR) == 0)
-       break;
-      sleep (1);
-    }
-  if (i == MAX_TRIES)
-    {
-      set_errno (ETIMEDOUT);
-      goto err;
+      if (i == MAX_TRIES)
+       {
+         set_errno (ETIMEDOUT);
+         __leave;
+       }
+      if (file.lock (fd, sizeof sf))
+       __leave;
+      if (read (fd, &sf, sizeof sf) != sizeof sf)
+       __leave;
+      sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, sf.value,
+                            wasopen);
+      file.unlock (fd);
+      if (sem == SEM_FAILED)
+       __leave;
+      /* If wasopen is set, the semaphore was already opened and we already have
+        an open file descriptor pointing to the file.  This means, we have to
+        close the file descriptor created in this call.  It won't be stored
+        anywhere anyway. */
+      if (wasopen)
+       close (fd);
+      return sem;
     }
-  if (file.lock (fd, sizeof sf))
-    goto err;
-  if (read (fd, &sf, sizeof sf) != sizeof sf)
-    goto err;
-  sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, sf.value, wasopen);
-  file.unlock (fd);
-  if (sem == SEM_FAILED)
-    goto err;
-  /* If wasopen is set, the semaphore was already opened and we already have
-     an open file descriptor pointing to the file.  This means, we have to
-     close the file descriptor created in this call.  It won't be stored
-     anywhere anyway. */
-  if (wasopen)
-    close (fd);
-  return sem;
-
-err:
+  __except (EFAULT) {}
+  __endtry
   /* Don't let following function calls change errno */
   save_errno save;
 
-  file.unlock (fd);
+  if (fd >= 0)
+    file.unlock (fd);
   if (created)
     unlink (semname);
   if (sem != SEM_FAILED)
@@ -1178,6 +905,8 @@ err:
   return SEM_FAILED;
 }
 
+extern "C" off_t lseek64 (int, off_t, int);
+
 int
 _sem_close (sem_t *sem, bool do_close)
 {
This page took 0.056983 seconds and 5 git commands to generate.