Page MenuHomeFreeBSD

fix sys_write error, only need SIGPIPE for EPIPE and socket
Needs ReviewPublic

Authored by shichun_ma_dell.com on Feb 10 2021, 12:10 AM.
Tags
None
Referenced Files
Unknown Object (File)
Mar 7 2024, 1:58 AM
Unknown Object (File)
Mar 7 2024, 12:52 AM
Unknown Object (File)
Mar 7 2024, 12:00 AM
Unknown Object (File)
Dec 20 2023, 5:47 AM
Unknown Object (File)
Aug 16 2023, 8:17 AM
Unknown Object (File)
Jun 27 2023, 7:07 AM
Unknown Object (File)
Apr 20 2023, 1:51 PM
Unknown Object (File)
Mar 8 2023, 2:19 AM
Subscribers
This revision needs review, but all specified reviewers are disabled or inactive.

Details

Reviewers
hselasky
Summary

by spec of POSIX, it has below define:
PIPE fd is connected to a pipe or socket whose reading end is closed. When this happens the writing process will also receive a SIGPIPE signal. (Thus, the write return value is seen only if the program catches, blocks or ignores this signal.)

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

shichun_ma_dell.com created this revision.

I don't quite understand what the goal of this change is? That is, are there other types of file descriptors returning EPIPE that trigger SIGPIPE that aren't either sockets or pipes and moving this fixes that?

@jhb, Here is one example:

  1. in function nfslock_write, it call nfslockdans, and it's possible that nfslockdans encounter EPIPE error.
  2. application's expectation is jut got write error with return error EPIPE, while freeBSD kernel send extra signal SIGPIPE, this will cause application killed by unexpected signal.

The goal of this change is to avoid unnecessary "signal SIGPIPE" sending in kernel.

There is no such function as nfslock_write.

For start, show the call stack for the point where EPIPE is returned initially, and you think that it should not.

@kib, sorry just realize that nfslock_write is a function in FreeBSD 12.0.
I don't have exact backtrace for it, this is an issue I debugs days before. Here is what I did. I implemented /dev/hidraw.
When run same app on Linux system, it has below strace. While there is signal SIGPIPE after write error.
Then I checked the code, and got that tdsignal(td, SIGPIPE) will be called from dofilewrite.
Here is the piece info from the whole trace file.

16906 3597 openat(AT_FDCWD, "/dev/hidraw1", O_RDWR) = 9
16907 3597 write(9, "\6\3", 2) = -1 EPIPE (Broken pipe)
16908 3597 close(9) = 0

So from what I was able to decipher from your response, you have some custom driver that has a method returning EPIPE that get returned to the write syscall, right?

Then the obvious suggestion is 'do not do that'.

WRT to EPIPE translating to SIGPIPE, POSIX indeed only mentions pipes and sockets, but this is because POSIX does not define any other type of non-regular files. I believe our behavior is compliant, and I am not sure that limiting SIGPIPE to pipes and fifos is the right route.

In other words I do not strongly object against your proposal, but also I am not sure that this is the right reaction to the behavior of your code that you found unexpected.

I agree with @kib in that I think a character device driver should only return EPIPE if it expects to send a SIGPIPE. If you don't want a SIGPIPE, then use a different errno value for the error condition in question.

I make a driver that compatable with Linux. From the application, it will not see it running on FreeBSD or Linux.
On linux, it will encounter same error without this signal sending. If I change error code, it will behave differently from linux.
I think others will also encounter similar issue , why not make a genric change that benifit all?