1 /* Basic tests for Linux process_madvise.
2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <array_length.h>
23 #include <support/check.h>
24 #include <support/process_state.h>
25 #include <support/support.h>
26 #include <support/xsocket.h>
27 #include <support/xunistd.h>
29 #include <sys/pidfd.h>
32 /* The pair of sockets used for coordination. The subprocess uses
34 static int sockets
[2];
36 static long int page_size
;
39 exit_subprocess (int dummy
)
47 /* In case something goes wrong with parent before pidfd_send_signal. */
48 support_create_timer (5, 0, false, exit_subprocess
);
50 void *p1
= xmmap (NULL
, page_size
* 2, PROT_READ
| PROT_WRITE
,
51 MAP_PRIVATE
| MAP_ANONYMOUS
, -1);
53 void *p2
= xmmap (NULL
, page_size
, PROT_READ
| PROT_WRITE
,
54 MAP_PRIVATE
| MAP_ANONYMOUS
, -1);
55 xmunmap(p2
, page_size
);
57 xsendto (sockets
[1], &(struct iovec
) { p1
, page_size
* 2 },
58 sizeof (struct iovec
), 0, NULL
, 0);
60 xsendto (sockets
[1], &(struct iovec
) { p2
, page_size
},
61 sizeof (struct iovec
), 0, NULL
, 0);
71 page_size
= sysconf (_SC_PAGE_SIZE
);
74 int r
= pidfd_open (-1, 0);
77 FAIL_UNSUPPORTED ("kernel does not support pidfd_open, skipping test");
79 TEST_COMPARE (errno
, EINVAL
);
82 TEST_COMPARE (socketpair (AF_UNIX
, SOCK_STREAM
, 0, sockets
), 0);
92 int pidfd
= pidfd_open (pid
, 0);
93 TEST_VERIFY (pidfd
!= -1);
95 /* The target process is going to send us two iovec's. The first one points
96 to a valid mapping, the other points to a previously valid mapping which
97 has now been unmapped. */
100 xrecvfrom (sockets
[0], &iv
, sizeof (iv
), 0, NULL
, 0);
102 /* We expect this to succeed in the target process because the mapping
104 ssize_t ret
= process_madvise (pidfd
, &iv
, 1, MADV_COLD
, 0);
105 if (ret
== -1 && errno
== ENOSYS
)
106 FAIL_UNSUPPORTED ("kernel does not support process_madvise, skipping"
108 TEST_COMPARE (ret
, 2 * page_size
);
113 xrecvfrom (sockets
[0], &iv
, sizeof (iv
), 0, NULL
, 0);
115 /* We expect this to fail in the target process because the second iovec
116 points to an unmapped region. The target process arranges for this to
118 TEST_COMPARE (process_madvise (pidfd
, &iv
, 1, MADV_COLD
, 0), -1);
119 TEST_COMPARE (errno
, ENOMEM
);
123 struct iovec iv
[IOV_MAX
+ 1];
124 TEST_COMPARE (process_madvise (pidfd
, iv
, array_length (iv
), MADV_COLD
,
126 TEST_COMPARE (errno
, EINVAL
);
129 TEST_COMPARE (pidfd_send_signal (pidfd
, SIGKILL
, NULL
, 0), 0);
132 int r
= waitid (P_PIDFD
, pidfd
, &info
, WEXITED
);
134 TEST_COMPARE (info
.si_status
, SIGKILL
);
135 TEST_COMPARE (info
.si_code
, CLD_KILLED
);
138 TEST_COMPARE (pidfd_send_signal (pidfd
, SIGKILL
, NULL
, 0), -1);
139 TEST_COMPARE (errno
, ESRCH
);
144 #include <support/test-driver.c>