From 33643eff5a3b7c44c54330141d6ed71c8739fde4 Mon Sep 17 00:00:00 2001 From: David Collard Date: Tue, 10 Jan 2023 20:32:23 -0500 Subject: [PATCH] Added `mq_timedreceive` to `::nix::mqueue`. --- CHANGELOG.md | 2 ++ src/mqueue.rs | 26 ++++++++++++++++++++++++++ test/test_mq.rs | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ff4176c87..9fb4b2932b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ This project adheres to [Semantic Versioning](https://semver.org/). (#[1662](https://github.com/nix-rust/nix/pull/1662)) - Added `CanRaw` to `SockProtocol` and `CanBcm` as a separate `SocProtocol` constant. ([#1912](https://github.com/nix-rust/nix/pull/1912)) +- Added `mq_timedreceive` to `::nix::mqueue`. + ([#1966])(https://github.com/nix-rust/nix/pull/1966) ### Changed diff --git a/src/mqueue.rs b/src/mqueue.rs index 33599bf91d..ac183eb55a 100644 --- a/src/mqueue.rs +++ b/src/mqueue.rs @@ -197,6 +197,32 @@ pub fn mq_receive( Errno::result(res).map(|r| r as usize) } +feature! { + #![feature = "time"] + use crate::sys::time::TimeSpec; + /// Receive a message from a message queue with a timeout + /// + /// See also ['mq_timedreceive(2)'](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html) + pub fn mq_timedreceive( + mqdes: &MqdT, + message: &mut [u8], + msg_prio: &mut u32, + abstime: &TimeSpec, + ) -> Result { + let len = message.len() as size_t; + let res = unsafe { + libc::mq_timedreceive( + mqdes.0, + message.as_mut_ptr() as *mut c_char, + len, + msg_prio as *mut u32, + abstime.as_ref(), + ) + }; + Errno::result(res).map(|r| r as usize) + } +} + /// Send a message to a message queue /// /// See also [`mq_send(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html) diff --git a/test/test_mq.rs b/test/test_mq.rs index 7b48e7ac78..f232434e12 100644 --- a/test/test_mq.rs +++ b/test/test_mq.rs @@ -3,9 +3,13 @@ use std::ffi::CString; use std::str; use nix::errno::Errno; -use nix::mqueue::{mq_attr_member_t, mq_close, mq_open, mq_receive, mq_send}; +use nix::mqueue::{ + mq_attr_member_t, mq_close, mq_open, mq_receive, mq_send, mq_timedreceive, +}; use nix::mqueue::{MQ_OFlag, MqAttr}; use nix::sys::stat::Mode; +use nix::sys::time::{TimeSpec, TimeValLike}; +use nix::time::{clock_gettime, ClockId}; // Defined as a macro such that the error source is reported as the caller's location. macro_rules! assert_attr_eq { @@ -55,6 +59,37 @@ fn test_mq_send_and_receive() { assert_eq!(msg_to_send, str::from_utf8(&buf[0..len]).unwrap()); } +#[test] +fn test_mq_timedreceive() { + const MSG_SIZE: mq_attr_member_t = 32; + let attr = MqAttr::new(0, 10, MSG_SIZE, 0); + let mq_name = &CString::new(b"/a_nix_test_queue".as_ref()).unwrap(); + + let oflag0 = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; + let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH; + let r0 = mq_open(mq_name, oflag0, mode, Some(&attr)); + if let Err(Errno::ENOSYS) = r0 { + println!("message queues not supported or module not loaded?"); + return; + }; + let mqd0 = r0.unwrap(); + let msg_to_send = "msg_1"; + mq_send(&mqd0, msg_to_send.as_bytes(), 1).unwrap(); + + let oflag1 = MQ_OFlag::O_CREAT | MQ_OFlag::O_RDONLY; + let mqd1 = mq_open(mq_name, oflag1, mode, Some(&attr)).unwrap(); + let mut buf = [0u8; 32]; + let mut prio = 0u32; + let abstime = + clock_gettime(ClockId::CLOCK_REALTIME).unwrap() + TimeSpec::seconds(1); + let len = mq_timedreceive(&mqd1, &mut buf, &mut prio, &abstime).unwrap(); + assert_eq!(prio, 1); + + mq_close(mqd1).unwrap(); + mq_close(mqd0).unwrap(); + assert_eq!(msg_to_send, str::from_utf8(&buf[0..len]).unwrap()); +} + #[test] fn test_mq_getattr() { use nix::mqueue::mq_getattr;