Skip to content

Prevent SIGPIPE being sent#155

Open
schmijoe wants to merge 2 commits intoMusicPlayerDaemon:masterfrom
schmijoe:master
Open

Prevent SIGPIPE being sent#155
schmijoe wants to merge 2 commits intoMusicPlayerDaemon:masterfrom
schmijoe:master

Conversation

@schmijoe
Copy link
Copy Markdown

@schmijoe schmijoe commented Apr 9, 2026

When trying to call mpd_async_write for a server that has disconnected, send makes the kernel generate SIGPIPE, which will terminate the calling process if it is not ignored. (Some clients like ncmpcpp ignore SIGPIPE, and use the EPIPE error generated by send to handle the error which seems like the sensible thing to do.)

This SIGPIPE can confuse processes which rely on SIGPIPE to terminate when the reading end of stdout has been closed. (like a status bar content generator.)

This sets the MSG_NOSIGNAL flag for send, which prevents SIGPIPE from being sent.

@MaxKellermann
Copy link
Copy Markdown
Member

This is the default behavior of UNIX-like operating systems, for some historic reason. Should we really override that? Applications can choose the behavior by installing a SIGPIPE handler (or masking the signal), but if we use MSG_NOSIGNAL, applications have no choice anymore. What is your rationale for that?

@schmijoe
Copy link
Copy Markdown
Author

schmijoe commented Apr 9, 2026

I'm only learning about SIGPIPE myself at the moment, but from what I understand SIGPIPE is mainly used to simplify error handling for applications so you can write to stdout without checking for EPIPE all the time. (So for example in cat file | head -5 the cat process can terminate early once head has closed its end of the pipe, without needing to check whether every write to stdout succeeded.)

I looked at some mpd clients listed in https://www.musicpd.org/clients/, and some of them ignore SIGPIPE, others leave it at the default, which means the client would terminate when the mpd server stops/restarts, which is probably not the intended behavior. send still gives error EPIPE, so the server disconnecting can be handled that way, which probably makes more sense.

Also I think the client terminating due to a SIGPIPE when the server restarts/stops might give some debugging headaches to people not to familiar with UNIX signals, as here the default behavior is probably not the one that would be expected.

For example i3status is using SIGPIPE to get notified when no one is reading from stdout anymore. If someone would write an mpd module for it, i3status would also exit when the mpd server stopped.
And I don't think there is a good method to check which file descriptor generated a SIGPIPE, so it would not be possible to check if SIGPIPE came from stdout or the mpd socket.

@MaxKellermann
Copy link
Copy Markdown
Member

MaxKellermann commented Apr 9, 2026

some of them ignore SIGPIPE, others leave it at the default

Those who leave it at the default will get default behavior. Those who do not want default behavior shall opt out of the default behavior.

I don't like that default behavior - it's a bad design for people who are too lazy to implement proper error handling. I wish SIGPIPE had never been invented. All of my software disables SIGPIPE.
But for libraries, there must be a good justification to ignore the application's choice.
I'm not saying your suggestion is bad. I want to ensure that you thought about all the implications and weighed all the pros and cons, because when you propose to change this, all this work is up to you. Anybody can change a line of code, but 99.99% of the work is thinking whether that's the right thing.

For example i3status is using SIGPIPE to get notified when no one is reading from stdout anymore.

That's not how SIGPIPE works. That would be more akin to SIGHUP.

SIGPIPE is not a notification of some external event. You only ever get SIGPIPE when failing to write. As long as you don't write to that pipe, you won't get SIGPIPE.

@schmijoe
Copy link
Copy Markdown
Author

schmijoe commented Apr 9, 2026

For example i3status is using SIGPIPE to get notified when no one is reading from stdout anymore.

That's not how SIGPIPE works. That would be more akin to SIGHUP.
Sorry for my imprecise wording, I meant it writes to stdout (without checking for errors) untill terminated by SIGPIPE.

My point is that since libmpdclient is forcibly emitting SIGPIPE without control of the library user, using SIGPIPE as above (which I believe to be the intended use case of SIGPIPE) is no longer possible. As far as I can tell SIGPIPE is only useful if one can control which writes would generate them.
Therefore it would be nice to either introduce the option to use MSG_NOSIGNAL in libmpdclient, or to change the default behavior to always set MSG_NOSIGNAL. (Which I know is risky buisness. I have superficially looked at some mpd clients and as I said they either ignore SIGPIPE, or seem to be unaware that libmpdclient might cause SIGPIPE.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants