Skip to content

Commit

Permalink
Merge #1966
Browse files Browse the repository at this point in the history
1966: Added `mq_timedreceive` to `::nix::mqueue`. r=asomers a=DavidCollard

Noticed when working on a project that `mq_timedreceive` is missing from the `mqueue` module.

Not entirely familiar with best practices around feature gating in tests - I feel like I might have messed up by not including a `#[cfg(feature = "time")]`. Would like a little guidance there.

Co-authored-by: David Collard <davidcollardprofessional@gmail.com>
  • Loading branch information
bors[bot] and DavidCollard committed Jan 11, 2023
2 parents 73e3c99 + 33643ef commit ef70d9e
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -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

Expand Down
26 changes: 26 additions & 0 deletions src/mqueue.rs
Expand Up @@ -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<usize> {
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)
Expand Down
37 changes: 36 additions & 1 deletion test/test_mq.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit ef70d9e

Please sign in to comment.