[LTP] connect01: Convert to new API

linuxtestproject.agent@gmail.com linuxtestproject.agent@gmail.com
Thu Jun 4 09:15:25 CEST 2026


On Thu, Jun 04, 2026 at 04:49:55 +0000, Wei Gao wrote:
> connect01: Convert to new API
> connect01: Add negative tests

Hi Wei,

Overall the series is in good shape. The conversion to the new API is
clean and the new EPROTOTYPE/EACCES test cases make sense. One bug needs
fixing and there are a few minor observations.

---
Patch 1: connect01: Convert to new API

> Convert the connect01 test case from the legacy LTP API to the new
> tst_test API.
>
> Refactor the test according to reviewer feedback:
> - Simplified the server child process to a single accept/exit loop.
> - Moved the server lifecycle to the global setup/cleanup.
> - The server now accepts a single connection for the EISCONN test case
>   and exits immediately, which avoids blocking the test runner.
> - Centralized test case initialization into the global setup.
> - Used tst_get_bad_addr() for the EFAULT test case to ensure
>   architectural compatibility.

The bulleted list is fine, though LTP commit messages generally prefer
plain prose over bullet points for the body.

> +static void start_server(struct sockaddr_in *sock)
> +{
> +	socklen_t slen = sizeof(*sock);
> +
> +	sock->sin_family = AF_INET;
> +	sock->sin_port = 0;
> +	sock->sin_addr.s_addr = INADDR_ANY;
> +
> +	fd_server = SAFE_SOCKET(PF_INET, SOCK_STREAM, 0);
> +	SAFE_BIND(fd_server, (struct sockaddr *)sock, slen);
> +	SAFE_LISTEN(fd_server, 10);
> +	SAFE_GETSOCKNAME(fd_server, (struct sockaddr *)sock, &slen);
> +
> +	pid = SAFE_FORK();
> +
> +	if (!pid) {
> +		int nfd = SAFE_ACCEPT(fd_server, NULL, NULL);
> +
> +		SAFE_CLOSE(nfd);
> +		exit(0);
> +	}
> +	SAFE_CLOSE(fd_server);
> +}

The single-accept server child is a nice simplification. Note that
fd_server is closed in the parent here but the static variable still
holds the (now-closed) fd number. cleanup() doesn't close fd_server,
which is correct since the parent already closed it. No issue, but
mentioning for clarity.

> +	if (fd_socket > 0)
> +		SAFE_CLOSE(fd_socket);
> +	if (fd_null > 0)
> +		SAFE_CLOSE(fd_null);
> +	if (fd_connected > 0)
> +		SAFE_CLOSE(fd_connected);

Nit: these guards should be `>= 0` (or `!= -1`) since a valid fd can
theoretically be 0 if stdin is closed before the test runs. Using `> 0`
works in practice (socket fds are typically > 2) but is technically
incorrect. This is a pre-existing LTP pattern, so not a blocker.

Patch 1 otherwise looks correct. The test case order is fine — after
ECONNREFUSED the TCP socket returns to TCP_CLOSE state, and the
subsequent EAFNOSUPPORT check happens before any connection attempt, so
fd_socket reuse is safe here.

---
Patch 2: connect01: Add negative tests

> +	{&fd_unix_dgram, &sock4, sizeof(sock4), EPROTOTYPE,
> +		"socket type does not support the protocol"},

The EPROTOTYPE errno is correct: connecting an AF_UNIX SOCK_DGRAM
socket to a path bound by a SOCK_STREAM server returns -EPROTOTYPE in
unix_find_other(). ✓

> +	{&fd_unix_stream, &sock4, sizeof(sock4), EACCES,
> +		"write permission is denied on the socket file"},

> +	SAFE_CHMOD(SOCK_FILE, 0700);

Correct: the socket file is owned by root with mode 0700. The "nobody"
user has no write permission on it, so connect() returns EACCES. ✓

> +static void verify_connect(unsigned int i)
> +{
> +	struct test_case_t *tc = &tcases[i];
> +	void *addr = tc->addr ? tc->addr : bad_addr;
> +
> +	if (tc->exp_errno == EACCES) {
> +		if (!SAFE_FORK()) {
> +			SAFE_SETUID(pw->pw_uid);
> +			TST_EXP_FAIL(sys_connect(*tc->fd, addr, tc->salen),
> +				tc->exp_errno, "%s", tc->desc);
> +			exit(0);
> +		}
> +	} else {

BUG: The parent never waits for the child. After SAFE_FORK() returns
the child PID (the `if (!SAFE_FORK())` branch is false in the parent),
the parent returns immediately from verify_connect() without reaping
the child. The child becomes a zombie and there is a race condition:
the next test iteration may start before the child has reported its
result via TST_EXP_FAIL.

The established LTP pattern for this (see e.g. msgget02.c) is to call
tst_reap_children() in the parent after the fork:

	if (tc->exp_errno == EACCES) {
		if (!SAFE_FORK()) {
			SAFE_SETUID(pw->pw_uid);
			TST_EXP_FAIL(sys_connect(*tc->fd, addr, tc->salen),
				tc->exp_errno, "%s", tc->desc);
			exit(0);
		}
		tst_reap_children();
	} else {
		TST_EXP_FAIL(sys_connect(*tc->fd, addr, tc->salen),
			tc->exp_errno, "%s", tc->desc);
	}

> +	.needs_root = 1,
> +	.needs_tmpdir = 1,

Both are necessary and correct given the chmod and socket file creation.

---
Summary:

- Patch 1: Reviewed, looks good (nits only, not blocking)
- Patch 2: Needs fix — add tst_reap_children() after the SAFE_FORK()
  block in verify_connect()

Please send a v2 with the fix applied to patch 2.

Thanks,


More information about the ltp mailing list