sgx-lkl
sgx-lkl copied to clipboard
[Tests] "write" syscall generates both SIGPIPE and EPIPE
After analysis, I found that write system call on pipe is generating both SIGPIPE and EPIPE even though we register a sighandler for SIGPIPE. This behaviour differs from pipe documentation of linux(https://www.man7.org/linux/man-pages/man7/pipe.7.html) . Below text is from man page.
“If all file descriptors referring to the write end of a pipe have been closed, then an attempt to read(2) from the pipe will see end-of-file (read(2) will return 0). If all file descriptors referring to the read end of a pipe have been closed, then a write(2) will cause a SIGPIPE signal to be generated for the calling process. If the calling process is ignoring this signal, then write(2) fails with the error EPIPE. An application that uses pipe(2) and fork(2) should use suitable close(2) calls to close unnecessary duplicate file descriptors; this ensures that end-of-file and SIGPIPE/EPIPE are delivered when appropriate.”
@SeanTAllen, this looks as if it’s related to the signal delivery. I suspect there may be something in how the syscall handler checks for signals that is wrong here.
Assigning myself so I don't lose track of this given it might be related to the signal handling stuff I've been looking at.
@shaikshavali1 do you have a minimal example that demonstrates the problem?
Test case Description:
The original test case is to check that the child process is killed due to “broken pipe” or not. Code snippet (original file): https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/syscalls/pipe/pipe02.c
This test case is modified to work as a single process. In modified code, below operations are performed.
- Signal handler is registered to catch SIGPIPE
- opens the pipe
- Perform dummy read and write
- Close read descriptor and perform write operation
- Check for SIGPIPE and EPIPE error.
Code snippet (modified code patch): https://github.com/lsds/sgx-lkl/blob/89234d3afea356250195964fa70f1bea360312ba/tests/ltp/patches/fix_pipe_pipe02.patch#L88
GDB Logs:
ksys_write (fd=5, buf=0x7fff3dbed274 "aaaaaaaaaa", count=5) at fs/read_write.c:602
(gdb) bt#0 ksys_write (fd=5, buf=0x7fff3dbed274 "aaaaaaaaaa", count=5) at fs/read_write.c:602
1 0x00007fff00209479 in __do_sys_write (count=<optimized out>, buf=<optimized out>, fd=<optimized out>) at fs/read_write.c:623
2 __se_sys_write (fd=<optimized out>, buf=<optimized out>, count=<optimized out>) at fs/read_write.c:620
3 0x00007fff0018becf in run_syscall (params=<optimized out>, no=<optimized out>) at arch/lkl/kernel/syscalls.c:44
4 lkl_syscall (no=5, params=0x7fff40a72cf0) at arch/lkl/kernel/syscalls.c:192
5 0x00007fff000e52c0 in write ()
6 0x0000000000000005 in ?? ()
7 0x00007fff3dbed274 in ?? ()
8 0x0000000000000005 in ?? ()
9 0x0000000000000000 in ?? ()
(gdb) bt
0 ksys_write (fd=5, buf=0x7fff3dbed274 "aaaaaaaaaa", count=5) at fs/read_write.c:602
1 0x00007fff00209479 in __do_sys_write (count=<optimized out>, buf=<optimized out>, fd=<optimized out>) at fs/read_write.c:623
2 __se_sys_write (fd=<optimized out>, buf=<optimized out>, count=<optimized out>) at fs/read_write.c:620
3 0x00007fff0018becf in run_syscall (params=<optimized out>, no=<optimized out>) at arch/lkl/kernel/syscalls.c:44
4 lkl_syscall (no=5, params=0x7fff40a72cf0) at arch/lkl/kernel/syscalls.c:192
5 0x00007fff000e52c0 in write ()
6 0x0000000000000005 in ?? ()
7 0x00007fff3dbed274 in ?? ()
8 0x0000000000000005 in ?? ()
9 0x0000000000000000 in ?? ()
(gdb)
As per the man page the write should generate SIGPIPE if signal handler is registered. But, here EPIPE is also returned from write.
Thanks. Is the SIGPIPE received?
@prp, Yes SIGPIPE received.
I believe the write
call should return EINTR
. Because signals are not being delivered to the wrong Linux task (#644), we are not setting substituting EINTR
for the syscall return value in lkl_syscall
. This is probably going to be fixed by the fix #644.
Unassigning myself as this is now a p2.