Reputation: 862
I want to use a pipe as an internal message Queue like desribed here: posix pipe as a work queue
According to the documentation of glibc the write to the pipe is atomic if the data is smaller than PIPE_BUF. https://www.gnu.org/software/libc/manual/html_node/Pipe-Atomicity.html#Pipe-Atomicity
But: write can get interrupted if a signal occurs. Lets assume, the write
is blocked because the pipe is nearly full. Now there occurs a signal. Would that data be atomicly written to the pipe?
template <typename T>
ssize_t put(const T& data)
{
static_assert(sizeof(T) < PIPE_BUF, "We use the atomic property of the pipe write. So sizeof(T) MUST be smaller than PIPE_BUF");
int written;
const size_t id = T::value;
written = write(m_fds[write_fd], &id, sizeof(size_t));
assert(written == sizeof(size_t));
const size_t sT = sizeof(T);
write(m_fds[write_fd], &sT, sizeof(size_t));
assert(written == sizeof(size_t));
write(m_fds[write_fd], &data, sizeof(T)); // * this blocks in example
assert(written == sizeof(T));
return sizeof(T);
}
Upvotes: 1
Views: 112
Reputation: 10947
Atomic just means that "the whole amount written in one operation is not interleaved with data from any other process."
Signal interruption is slightly different. According to the man page of signal, a pipe is a "slow device". Therefore, unless SA_RESTART
has been set, the write
operation will return success with the number of data written. Therefore, better to always check the return value of write to ensure that all data has been written. Alternatively, you can mask the possible signals.
Upvotes: 1