Skip to content

Commit

Permalink
Add regression test for hangup on pipe operations
Browse files Browse the repository at this point in the history
This tests the problem fixed by the patch
https://www.spinics.net/lists/linux-api/msg49731.html.

Signed-off-by: Marius Kittler <[email protected]>
Signed-off-by: Richard Palethorpe <[email protected]>
Reviewed-by: Richard Palethorpe <[email protected]>

[rpalethorpe: Made sure to perform the test on the final pipe which is
effected by the soft-limit kicking in. Fixed multiple
iterations. Removed comments. Printed the buffer size after soft-limit
is reached. Added git tags]
  • Loading branch information
Martchus authored and Richard Palethorpe committed Nov 27, 2023
1 parent fac8457 commit 4e3bb6b
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 0 deletions.
1 change: 1 addition & 0 deletions runtest/syscalls
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,7 @@ pipe11 pipe11
pipe12 pipe12
pipe13 pipe13
pipe14 pipe14
pipe15 pipe15

pipe2_01 pipe2_01
pipe2_02 pipe2_02
Expand Down
1 change: 1 addition & 0 deletions testcases/kernel/syscalls/pipe/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
/pipe12
/pipe13
/pipe14
/pipe15
94 changes: 94 additions & 0 deletions testcases/kernel/syscalls/pipe/pipe15.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 SUSE LLC Marius Kittler <[email protected]>
*/

/*\
* [Description]
*
* This is a regression test for hangup on pipe operations. See
* https://www.spinics.net/lists/linux-api/msg49762.html for
* additional context. It tests that pipe operations do not block
* indefinitely when going to the soft limit on the total size of
* all pipes created by a single user.
*/

#define _GNU_SOURCE
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>

#include "tst_test.h"
#include "tst_safe_stdio.h"
#include "tst_safe_macros.h"

static int pipe_count;
static int *pipes;
static char *buffer;

static void run(void)
{
const int *const pipe = pipes + 2 * (pipe_count - 1);
const int buffer_size = SAFE_FCNTL(pipe[1], F_GETPIPE_SZ);

tst_res(TINFO, "Soft-limited buffer size: %d bytes", buffer_size);
SAFE_WRITE(1, pipe[1], buffer, buffer_size);
SAFE_READ(1, pipe[0], buffer, buffer_size - 1);
SAFE_WRITE(1, pipe[1], buffer, 1);
tst_res(TPASS, "Pipe operation did not block");

SAFE_READ(1, pipe[0], buffer, 2);
}

static void setup(void)
{
int pipe[2];
int page_size = getpagesize(), soft_limit;
struct rlimit nfd;

SAFE_PIPE(pipe);
const int buffer_size = SAFE_FCNTL(pipe[1], F_GETPIPE_SZ);
SAFE_CLOSE(pipe[0]);
SAFE_CLOSE(pipe[1]);

SAFE_FILE_SCANF("/proc/sys/fs/pipe-user-pages-soft", "%i", &soft_limit);
pipe_count = soft_limit * page_size / buffer_size;

tst_res(TINFO, "Soft limit for pipes: %i pages", soft_limit);
tst_res(TINFO, "Buffer size: %d byte", buffer_size);
tst_res(TINFO, "Creating %i pipes", pipe_count);

SAFE_GETRLIMIT(RLIMIT_NOFILE, &nfd);
if (nfd.rlim_max < (unsigned long)pipe_count)
tst_brk(TCONF, "NOFILE limit max too low: %lu < %i", nfd.rlim_max, pipe_count);
if (nfd.rlim_cur < nfd.rlim_max) {
nfd.rlim_cur = nfd.rlim_max;
SAFE_SETRLIMIT(RLIMIT_NOFILE, &nfd);
}

buffer = SAFE_MALLOC(buffer_size);
pipes = SAFE_MALLOC(pipe_count * 2 * sizeof(int));
for (int i = 0; i < pipe_count; ++i)
SAFE_PIPE(pipes + i * 2);

}

static void cleanup(void)
{
for (int i = 0; i < pipe_count * 2; i++)
if (pipes[i] > 0)
SAFE_CLOSE(pipes[i]);
if (pipes)
free(pipes);
if (buffer)
free(buffer);
}

static struct tst_test test = {
.setup = setup,
.test_all = run,
.cleanup = cleanup,
.tags = (const struct tst_tag[]){
{"linux-git", "46c4c9d1beb7"},
},
};

0 comments on commit 4e3bb6b

Please sign in to comment.