diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2021-05-25 16:49:04 +0200 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2021-05-25 16:49:04 +0200 |
commit | b62450cf172971c7805143a39c6c491a7a3c9785 (patch) | |
tree | 73b1054bd5ee9ec6ccd2ccf644dc3cee5f372879 | |
parent | a4e074672aa61bd8b8a3b9493b9bdc85683e7604 (diff) | |
download | newlib-b62450cf172971c7805143a39c6c491a7a3c9785.zip newlib-b62450cf172971c7805143a39c6c491a7a3c9785.tar.gz newlib-b62450cf172971c7805143a39c6c491a7a3c9785.tar.bz2 |
Cygwin: POSIX msg queues: implement open/mq_open entirely in fhandler
The mq_open call is just a framework now. This patch moves the
entire functionality into fhandler_mqueue. To support standard
OS calls (as on Linux), make fhandler_mqueue a derived class from
fhandler_disk_file and keep the base handle the handle to the
default stream, to allow implementing O_PATH functionlaity as well
as reading from the file and NOT reading binary message queue data.
Implement a standard fhandler_mqueue::open method, allowing, for
instance, to touch a file under /dev/mqueue and if it doesn't exist,
to create a message queue file.
FIXME: This introduces a BAD HACK into path_conv::check, which needs
reviewing.
Keep the posix path intact in the fhandler, and change get_proc_fd_name
accordingly to return only the basename plus leading slash for
/proc/<PID>/fd.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
-rw-r--r-- | winsup/cygwin/fhandler.h | 19 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_mqueue.cc | 271 | ||||
-rw-r--r-- | winsup/cygwin/globals.cc | 1 | ||||
-rw-r--r-- | winsup/cygwin/path.cc | 12 | ||||
-rw-r--r-- | winsup/cygwin/posix_ipc.cc | 180 |
5 files changed, 293 insertions, 190 deletions
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 0ffc5a6..4c8fe0f 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -3103,11 +3103,15 @@ class fhandler_timerfd : public fhandler_base } }; -class fhandler_mqueue: public fhandler_base +class fhandler_mqueue: public fhandler_disk_file { struct mq_info mqi; - struct mq_info *_mqinfo (HANDLE, SIZE_T, mode_t, int, bool); + struct mq_info *_mqinfo (SIZE_T, mode_t, int, bool); + + struct mq_info *mqinfo_create (struct mq_attr *, mode_t, int); + struct mq_info *mqinfo_open (int); + void mq_open_finish (bool success, bool created); public: fhandler_mqueue (); @@ -3118,14 +3122,9 @@ public: char *get_proc_fd_name (char *); - struct mq_info *mqinfo_create (HANDLE _h, SIZE_T _s, mode_t _m, int _f) - { - return _mqinfo (_h, _s, _m, _f, false); - } - struct mq_info *mqinfo_open (HANDLE _h, SIZE_T _s, mode_t _m, int _f) - { - return _mqinfo (_h, _s, _m, _f, true); - } + int open (int, mode_t); + int mq_open (int, mode_t, struct mq_attr *); + struct mq_info *mqinfo () { return &mqi; } void fixup_after_fork (HANDLE); diff --git a/winsup/cygwin/fhandler_mqueue.cc b/winsup/cygwin/fhandler_mqueue.cc index 5f97264..6b0d98d 100644 --- a/winsup/cygwin/fhandler_mqueue.cc +++ b/winsup/cygwin/fhandler_mqueue.cc @@ -11,21 +11,124 @@ details. */ #include "path.h" #include "fhandler.h" #include "dtable.h" +#include <mqueue.h> +#include <sys/param.h> + +#define MSGSIZE(i) roundup((i), sizeof(long)) + +struct mq_attr defattr = { 0, 10, 8192, 0 }; /* Linux defaults. */ fhandler_mqueue::fhandler_mqueue () : - fhandler_base () + fhandler_disk_file () { - nohandle (true); close_on_exec (true); } +int +fhandler_mqueue::open (int flags, mode_t mode) +{ + /* FIXME: reopen by handle semantics missing yet */ + flags &= ~(O_NOCTTY | O_PATH | O_BINARY | O_TEXT); + return mq_open (flags, mode, NULL); +} + +int +fhandler_mqueue::mq_open (int oflags, mode_t mode, struct mq_attr *attr) +{ + NTSTATUS status; + IO_STATUS_BLOCK io; + PUNICODE_STRING mqstream; + OBJECT_ATTRIBUTES oa; + struct mq_info *mqinfo = NULL; + bool created = false; + + if ((oflags & ~(O_ACCMODE | O_CLOEXEC | O_CREAT | O_EXCL | O_NONBLOCK)) + || (oflags & O_ACCMODE) == O_ACCMODE) + { + set_errno (EINVAL); + return 0; + } + + /* attach a stream suffix to the NT filename, thus creating a stream. */ + mqstream = pc.get_nt_native_path (&ro_u_mq_suffix); + pc.get_object_attr (oa, sec_none_nih); + +again: + if (oflags & O_CREAT) + { + /* Create and disallow sharing */ + status = NtCreateFile (&get_handle (), + GENERIC_READ | GENERIC_WRITE | DELETE + | SYNCHRONIZE, &oa, &io, NULL, + FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE, + FILE_CREATE, + FILE_OPEN_FOR_BACKUP_INTENT + | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, 0); + if (!NT_SUCCESS (status)) + { + if (status == STATUS_OBJECT_NAME_COLLISION && (oflags & O_EXCL) == 0) + goto exists; + __seterrno_from_nt_status (status); + return 0; + } + if (pc.has_acls ()) + set_created_file_access (get_handle (), pc, mode); + created = true; + goto out; + } +exists: + /* Open the file, and loop while detecting a sharing violation. */ + while (true) + { + status = NtOpenFile (&get_handle (), + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &oa, &io, FILE_SHARE_VALID_FLAGS, + FILE_OPEN_FOR_BACKUP_INTENT + | FILE_SYNCHRONOUS_IO_NONALERT); + if (NT_SUCCESS (status)) + break; + if (status == STATUS_OBJECT_NAME_NOT_FOUND && (oflags & O_CREAT)) + goto again; + if (status != STATUS_SHARING_VIOLATION) + { + __seterrno_from_nt_status (status); + return -1; + } + Sleep (100L); + } +out: + /* We need the filename without STREAM_SUFFIX later on */ + mqstream->Length -= ro_u_mq_suffix.Length; + mqstream->Buffer[mqstream->Length / sizeof (WCHAR)] = L'\0'; + + if (created) + { + 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, up to Linux + 3.4. These max values make sure that the internal mq_fattr + structure can use 32 bit types. */ + if (attr->mq_maxmsg <= 0 || attr->mq_maxmsg > 32768 + || attr->mq_msgsize <= 0 || attr->mq_msgsize > 1048576) + set_errno (EINVAL); + else + mqinfo = mqinfo_create (attr, mode, oflags & O_NONBLOCK); + } + else + mqinfo = mqinfo_open (oflags & O_NONBLOCK); + mq_open_finish (mqinfo != NULL, created); + return mqinfo ? 1 : 0; +} + struct mq_info * -fhandler_mqueue::_mqinfo (HANDLE fh, SIZE_T filesize, mode_t mode, int flags, +fhandler_mqueue::_mqinfo (SIZE_T filesize, mode_t mode, int flags, bool just_open) { WCHAR buf[NAME_MAX + sizeof ("mqueue/XXX")]; UNICODE_STRING uname; - OBJECT_ATTRIBUTES attr; + OBJECT_ATTRIBUTES oa; NTSTATUS status; LARGE_INTEGER fsiz = { QuadPart: (LONGLONG) filesize }; PVOID mptr = NULL; @@ -38,33 +141,33 @@ fhandler_mqueue::_mqinfo (HANDLE fh, SIZE_T filesize, mode_t mode, int flags, __small_swprintf (buf, L"mqueue/mtx%s", get_name ()); RtlInitUnicodeString (&uname, buf); - InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE, + InitializeObjectAttributes (&oa, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE, get_shared_parent_dir (), everyone_sd (CYG_MUTANT_ACCESS)); - status = NtCreateMutant (&mqinfo ()->mqi_lock, CYG_MUTANT_ACCESS, &attr, + status = NtCreateMutant (&mqinfo ()->mqi_lock, CYG_MUTANT_ACCESS, &oa, FALSE); if (!NT_SUCCESS (status)) goto err; wcsncpy (buf + 7, L"snd", 3); /* same length, no RtlInitUnicodeString required */ - InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE, + InitializeObjectAttributes (&oa, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE, get_shared_parent_dir (), everyone_sd (CYG_EVENT_ACCESS)); - status = NtCreateEvent (&mqinfo ()->mqi_waitsend, CYG_EVENT_ACCESS, &attr, + status = NtCreateEvent (&mqinfo ()->mqi_waitsend, CYG_EVENT_ACCESS, &oa, NotificationEvent, FALSE); if (!NT_SUCCESS (status)) goto err; wcsncpy (buf + 7, L"rcv", 3); /* same length, same attributes, no more init required */ - status = NtCreateEvent (&mqinfo ()->mqi_waitrecv, CYG_EVENT_ACCESS, &attr, + status = NtCreateEvent (&mqinfo ()->mqi_waitrecv, CYG_EVENT_ACCESS, &oa, NotificationEvent, FALSE); if (!NT_SUCCESS (status)) goto err; - InitializeObjectAttributes (&attr, NULL, 0, NULL, NULL); - status = NtCreateSection (&mqinfo ()->mqi_sect, SECTION_ALL_ACCESS, &attr, - &fsiz, PAGE_READWRITE, SEC_COMMIT, fh); + InitializeObjectAttributes (&oa, NULL, 0, NULL, NULL); + status = NtCreateSection (&mqinfo ()->mqi_sect, SECTION_ALL_ACCESS, &oa, + &fsiz, PAGE_READWRITE, SEC_COMMIT, get_handle ()); if (!NT_SUCCESS (status)) goto err; @@ -100,22 +203,152 @@ err: return NULL; } +struct mq_info * +fhandler_mqueue::mqinfo_open (int flags) +{ + FILE_STANDARD_INFORMATION fsi; + IO_STATUS_BLOCK io; + NTSTATUS status; + mode_t mode; + + fsi.EndOfFile.QuadPart = 0; + status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi, + FileStandardInformation); + if (!NT_SUCCESS (status)) + { + __seterrno_from_nt_status (status); + return NULL; + } + if (get_file_attribute (get_handle (), pc, &mode, NULL, NULL)) + mode = STD_RBITS | STD_WBITS; + + return _mqinfo (fsi.EndOfFile.QuadPart, mode, flags, true); +} + +struct mq_info * +fhandler_mqueue::mqinfo_create (struct mq_attr *attr, mode_t mode, int flags) +{ + long msgsize; + off_t filesize = 0; + FILE_END_OF_FILE_INFORMATION feofi; + IO_STATUS_BLOCK io; + NTSTATUS status; + struct mq_info *mqinfo = NULL; + + msgsize = MSGSIZE (attr->mq_msgsize); + filesize = sizeof (struct mq_hdr) + + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize)); + feofi.EndOfFile.QuadPart = filesize; + status = NtSetInformationFile (get_handle (), &io, &feofi, sizeof feofi, + FileEndOfFileInformation); + if (!NT_SUCCESS (status)) + { + __seterrno_from_nt_status (status); + return NULL; + } + + mqinfo = _mqinfo (filesize, mode, flags, false); + + if (mqinfo) + { + /* Initialize header at beginning of file */ + /* Create free list with all messages on it */ + int8_t *mptr; + struct mq_hdr *mqhdr; + struct msg_hdr *msghdr; + + mptr = (int8_t *) mqinfo->mqi_hdr; + 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; + mqhdr->mqh_attr.mq_curmsgs = 0; + mqhdr->mqh_nwait = 0; + mqhdr->mqh_pid = 0; + mqhdr->mqh_head = 0; + mqhdr->mqh_magic = MQI_MAGIC; + long index = sizeof (struct mq_hdr); + mqhdr->mqh_free = index; + for (int i = 0; i < attr->mq_maxmsg - 1; i++) + { + msghdr = (struct msg_hdr *) &mptr[index]; + index += sizeof (struct msg_hdr) + msgsize; + msghdr->msg_next = index; + } + msghdr = (struct msg_hdr *) &mptr[index]; + msghdr->msg_next = 0; /* end of free list */ + } + + return mqinfo; +} + +void +fhandler_mqueue::mq_open_finish (bool success, bool created) +{ + NTSTATUS status; + HANDLE def_stream; + OBJECT_ATTRIBUTES oa; + IO_STATUS_BLOCK io; + + if (get_handle ()) + { + /* If we have an open queue stream handle, close it and set it to NULL */ + HANDLE queue_stream = get_handle (); + set_handle (NULL); + if (success) + { + /* In case of success, open the default stream for reading. This + can be used to implement various IO functions without exposing + the actual message queue. */ + pc.get_object_attr (oa, sec_none_nih); + status = NtOpenFile (&def_stream, GENERIC_READ | SYNCHRONIZE, + &oa, &io, FILE_SHARE_VALID_FLAGS, + FILE_OPEN_FOR_BACKUP_INTENT + | FILE_SYNCHRONOUS_IO_NONALERT); + if (NT_SUCCESS (status)) + set_handle (def_stream); + else /* Note that we don't treat this as an error! */ + { + debug_printf ("Opening default stream failed: status %y", status); + nohandle (true); + } + } + else if (created) + { + /* In case of error at creation time, delete the file */ + FILE_DISPOSITION_INFORMATION disp = { TRUE }; + + NtSetInformationFile (queue_stream, &io, &disp, sizeof disp, + FileDispositionInformation); + /* We also have to set the delete disposition on the default stream, + otherwise only the queue stream will get deleted */ + pc.get_object_attr (oa, sec_none_nih); + status = NtOpenFile (&def_stream, DELETE, &oa, &io, + FILE_SHARE_VALID_FLAGS, + FILE_OPEN_FOR_BACKUP_INTENT); + if (NT_SUCCESS (status)) + { + NtSetInformationFile (def_stream, &io, &disp, sizeof disp, + FileDispositionInformation); + NtClose (def_stream); + } + } + NtClose (queue_stream); + } +} + char * fhandler_mqueue::get_proc_fd_name (char *buf) { - return strcpy (buf, get_name ()); + return strcpy (buf, strrchr (get_name (), '/')); } int __reg2 fhandler_mqueue::fstat (struct stat *buf) { - int ret = fhandler_base::fstat (buf); + int ret = fhandler_disk_file::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 ()); - } + buf->st_dev = FH_MQUEUE; return ret; } diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc index d0c6046..3b25c28 100644 --- a/winsup/cygwin/globals.cc +++ b/winsup/cygwin/globals.cc @@ -153,6 +153,7 @@ const int __collate_load_error = 0; extern UNICODE_STRING _RDATA ro_u_natsyml = _ROU (L"SymbolicLink"); extern UNICODE_STRING _RDATA ro_u_natdev = _ROU (L"Device"); extern UNICODE_STRING _RDATA ro_u_npfs = _ROU (L"\\Device\\NamedPipe\\"); + extern UNICODE_STRING _RDATA ro_u_mq_suffix = _ROU (L":mqueue"); #undef _ROU /* This is an exported copy of environ which can be used by DLLs diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 2b48013..39ba175 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1225,6 +1225,18 @@ path_conv::check (const char *src, unsigned opt, set_exec (1); else if (issymlink () || issocket ()) set_exec (0); + + /* FIXME: bad hack alert!!! We need a better solution */ + +#define MQ_PATH "/dev/mqueue/" +#define MQ_LEN (sizeof (MQ_PATH) - 1) + + if (!strncmp (src, MQ_PATH, MQ_LEN)) + { + size_t len = strlen (src + MQ_LEN); + if (len > 0 && len <= NAME_MAX && !strpbrk (src + MQ_LEN, "/\\")) + dev.parse (FH_MQUEUE); + } } if (opt & PC_NOFULL) diff --git a/winsup/cygwin/posix_ipc.cc b/winsup/cygwin/posix_ipc.cc index 300a3f4..772072d 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 "tls_pbuf.h" #include <io.h> #include <sys/mman.h> #include <sys/param.h> @@ -24,8 +25,6 @@ details. */ #include <mqueue.h> #include <semaphore.h> -extern "C" int ftruncate64 (int fd, off_t length); - /* The prefix_len is the length of the path prefix including trailing "/" (or "/sem." for semaphores) as well as the trailing NUL. */ static struct @@ -300,39 +299,13 @@ shm_unlink (const char *name) files are created under /dev/mqueue. mq_timedsend and mq_timedreceive are implemented additionally. */ -#pragma pack (push, 4) -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) - -#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 = 0; - long msgsize, index; - off_t filesize = 0; va_list ap; - mode_t mode; + mode_t mode = 0; fhandler_mqueue *fh = NULL; - struct stat statbuff; - int8_t *mptr = NULL; - struct mq_hdr *mqhdr; - struct msg_hdr *msghdr; - struct mq_attr *attr; - struct mq_info *mqinfo = NULL; + struct mq_attr *attr = NULL; size_t len = strlen (name); char mqname[ipc_names[mqueue].prefix_len + len]; @@ -342,155 +315,36 @@ mq_open (const char *name, int oflag, ...) __try { - oflag &= (O_CREAT | O_EXCL | O_NONBLOCK); - nonblock = oflag & O_NONBLOCK; - oflag &= ~O_NONBLOCK; - - again: if (oflag & O_CREAT) { 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); - __leave; - } - /* 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 (ftruncate64 (fd, filesize) == -1) - __leave; - - /* Create file descriptor for mqueue */ - cygheap_fdnew fdm; - - if (fdm < 0) - __leave; - fh = (fhandler_mqueue *) build_fh_dev (*mqueue_dev, name); - if (!fh) - __leave; - - mqinfo = fh->mqinfo_create ((HANDLE) _get_osfhandle (fd), filesize, - mode, nonblock); - if (!mqinfo) - __leave; - - /* Initialize header at beginning of file */ - /* Create free list with all messages on it */ - mptr = (int8_t *) mqinfo->mqi_hdr; - 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; - mqhdr->mqh_attr.mq_curmsgs = 0; - mqhdr->mqh_nwait = 0; - mqhdr->mqh_pid = 0; - 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++) - { - msghdr = (struct msg_hdr *) &mptr[index]; - index += sizeof (struct msg_hdr) + msgsize; - msghdr->msg_next = index; - } - msghdr = (struct msg_hdr *) &mptr[index]; - msghdr->msg_next = 0; /* end of free list */ - - /* Initialization complete, turn off user-execute bit */ - if (fchmod (fd, mode) == -1) - __leave; - close (fd); - fdm = fh; - return (mqd_t) fdm; - } - - exists: - /* Open the file then memory map */ - if ((fd = open (mqname, 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 (mqname, &statbuff) == -1) - { - if (errno == ENOENT && (oflag & O_CREAT)) - { - close (fd); - fd = -1; - goto again; - } - __leave; - } - if ((statbuff.st_mode & S_IXUSR) == 0) - break; - sleep (1); - } - if (i == MAX_TRIES) - { - set_errno (ETIMEDOUT); - __leave; } /* Create file descriptor for mqueue */ - cygheap_fdnew fdm; + cygheap_fdnew fd; - if (fdm < 0) + if (fd < 0) __leave; - fh = (fhandler_mqueue *) build_fh_dev (*mqueue_dev, name); + fh = (fhandler_mqueue *) build_fh_name (mqname, + PC_OPEN | PC_POSIX + | PC_SYM_NOFOLLOW | PC_NULLEMPTY, + NULL); if (!fh) __leave; - mqinfo = fh->mqinfo_open ((HANDLE) _get_osfhandle (fd), statbuff.st_size, - statbuff.st_mode, nonblock); - if (!mqinfo) - __leave; - - close (fd); - fdm = fh; - return (mqd_t) fdm; + if (fh->mq_open (oflag, mode, attr)) + { + fd = fh; + return (mqd_t) fd; + } } __except (EFAULT) {} __endtry - /* Don't let following function calls change errno */ - save_errno save; - if (created) - unlink (mqname); - if (fd >= 0) - close (fd); if (fh) - { - fh->close (); - delete fh; - } + delete fh; return (mqd_t) -1; } @@ -921,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; @@ -1049,6 +905,8 @@ sem_open (const char *name, int oflag, ...) return SEM_FAILED; } +extern "C" off_t lseek64 (int, off_t, int); + int _sem_close (sem_t *sem, bool do_close) { |