schorsch_76
schorsch_76

Reputation: 862

posix pipe as message queue: What happens on blocked write + signal

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

Answers (1)

Claudio
Claudio

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

Related Questions