reddit/baseplate.py

Queues Should Set O_NONBLOCK

Closed this issue · 2 comments

def __init__(self, name: str, max_messages: int, max_message_size: int):
try:
self.queue = posix_ipc.MessageQueue(
name,
flags=posix_ipc.O_CREAT,
mode=0o0644,
max_messages=max_messages,
max_message_size=max_message_size,
)

See MQ_SEND(3) for details, but we should be setting O_NONBLOCK on created queues, and catching EAGAIN and working with that. That'll keep us from blocking on sends to the queue, which is a good opportunity to reclaim some precious performance by not waiting on a full queue.

From the manual:

       If the message queue is already full (i.e., the number of messages on the queue equals the queue's mq_maxmsg attribute), then, by default, mq_send() blocks until sufficient space becomes available to allow the
       message to be queued, or until the call is interrupted by a signal handler.  If the O_NONBLOCK flag is enabled for the message queue description, then the call instead fails immediately with the error EAGAIN.

Hmm. It's been a while since I wrote this, but I do remember testing blocking behavior. Do you have a repro of the process getting blocked?

FWIW, baseplate does set block = False a few lines later:

self.queue.block = False

And it sounds like the posix_ipc library does turn that into appropriate non-blocking behavior: https://semanchuk.com/philip/posix_ipc/#message_queue + https://github.com/osvenskan/posix_ipc/blob/38c7d500e445d15b799ea6e66c046032d805b050/posix_ipc_module.c#L1625-L1628

I stand corrected and will close this. This came up out of investigation into baseplate.go and I didn't catch that line you just tagged (which is correct and does exactly what I want).