1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved. 4f08c3bdfSopenharmony_ci * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com> 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * Test Description: 7f08c3bdfSopenharmony_ci * This case is designed to test whether pipe can wakeup all readers 8f08c3bdfSopenharmony_ci * when last writer closes. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * This is also a regression test for commit 6551d5c56eb0 11f08c3bdfSopenharmony_ci * ("pipe: make sure to wake up everybody when the last reader/writer closes"). 12f08c3bdfSopenharmony_ci * This bug was introduced by commit 0ddad21d3e99 ("pipe: use exclusive 13f08c3bdfSopenharmony_ci * waits when reading or writing"). 14f08c3bdfSopenharmony_ci */ 15f08c3bdfSopenharmony_ci#include <unistd.h> 16f08c3bdfSopenharmony_ci#include <sys/types.h> 17f08c3bdfSopenharmony_ci#include <sys/wait.h> 18f08c3bdfSopenharmony_ci#include <stdlib.h> 19f08c3bdfSopenharmony_ci#include "tst_test.h" 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_cistatic unsigned int tcases[] = { 22f08c3bdfSopenharmony_ci 2, 23f08c3bdfSopenharmony_ci 10, 24f08c3bdfSopenharmony_ci 27, 25f08c3bdfSopenharmony_ci 100 26f08c3bdfSopenharmony_ci}; 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_cistatic int fds[2]; 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_cistatic void do_child(unsigned int i) 31f08c3bdfSopenharmony_ci{ 32f08c3bdfSopenharmony_ci char buf; 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_ci SAFE_CLOSE(fds[1]); 35f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE(i); 36f08c3bdfSopenharmony_ci int ret = SAFE_READ(0, fds[0], &buf, 1); 37f08c3bdfSopenharmony_ci if (ret != 0) 38f08c3bdfSopenharmony_ci tst_res(TFAIL, "Wrong return from read %i", ret); 39f08c3bdfSopenharmony_ci exit(0); 40f08c3bdfSopenharmony_ci} 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_cistatic void verify_pipe(unsigned int n) 43f08c3bdfSopenharmony_ci{ 44f08c3bdfSopenharmony_ci int ret; 45f08c3bdfSopenharmony_ci unsigned int i, cnt = 0, sleep_us = 1, fail = 0; 46f08c3bdfSopenharmony_ci unsigned int child_num = tcases[n]; 47f08c3bdfSopenharmony_ci int pid[child_num]; 48f08c3bdfSopenharmony_ci 49f08c3bdfSopenharmony_ci SAFE_PIPE(fds); 50f08c3bdfSopenharmony_ci tst_res(TINFO, "Creating %d child processes", child_num); 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci for (i = 0; i < child_num; i++) { 53f08c3bdfSopenharmony_ci pid[i] = SAFE_FORK(); 54f08c3bdfSopenharmony_ci if (pid[i] == 0) 55f08c3bdfSopenharmony_ci do_child(i); 56f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAIT(i); 57f08c3bdfSopenharmony_ci TST_PROCESS_STATE_WAIT(pid[i], 'S', 0); 58f08c3bdfSopenharmony_ci } 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci SAFE_CLOSE(fds[0]); 61f08c3bdfSopenharmony_ci SAFE_CLOSE(fds[1]); 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci while (cnt < child_num && sleep_us < 1000000) { 64f08c3bdfSopenharmony_ci ret = waitpid(-1, NULL, WNOHANG); 65f08c3bdfSopenharmony_ci if (ret < 0) 66f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "waitpid()"); 67f08c3bdfSopenharmony_ci if (ret > 0) { 68f08c3bdfSopenharmony_ci cnt++; 69f08c3bdfSopenharmony_ci for (i = 0; i < child_num; i++) { 70f08c3bdfSopenharmony_ci if (pid[i] == ret) 71f08c3bdfSopenharmony_ci pid[i] = 0; 72f08c3bdfSopenharmony_ci } 73f08c3bdfSopenharmony_ci continue; 74f08c3bdfSopenharmony_ci } 75f08c3bdfSopenharmony_ci usleep(sleep_us); 76f08c3bdfSopenharmony_ci sleep_us *= 2; 77f08c3bdfSopenharmony_ci } 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci for (i = 0; i < child_num; i++) { 80f08c3bdfSopenharmony_ci if (pid[i]) { 81f08c3bdfSopenharmony_ci tst_res(TINFO, "pid %i still sleeps", pid[i]); 82f08c3bdfSopenharmony_ci fail = 1; 83f08c3bdfSopenharmony_ci SAFE_KILL(pid[i], SIGKILL); 84f08c3bdfSopenharmony_ci SAFE_WAIT(NULL); 85f08c3bdfSopenharmony_ci } 86f08c3bdfSopenharmony_ci } 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci if (fail) 89f08c3bdfSopenharmony_ci tst_res(TFAIL, "Closed pipe didn't wake up everyone"); 90f08c3bdfSopenharmony_ci else 91f08c3bdfSopenharmony_ci tst_res(TPASS, "Closed pipe waked up everyone"); 92f08c3bdfSopenharmony_ci} 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_cistatic struct tst_test test = { 95f08c3bdfSopenharmony_ci .test = verify_pipe, 96f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 97f08c3bdfSopenharmony_ci .forks_child = 1, 98f08c3bdfSopenharmony_ci .needs_checkpoints = 1, 99f08c3bdfSopenharmony_ci .tags = (const struct tst_tag[]) { 100f08c3bdfSopenharmony_ci {"linux-git", "6551d5c56eb"}, 101f08c3bdfSopenharmony_ci {} 102f08c3bdfSopenharmony_ci } 103f08c3bdfSopenharmony_ci}; 104