Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion qkernel/src/syscalls/sys_poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ pub fn DoSelect(
if (events & SELECT_EXCEPT_EVENTS) != 0 {
bitSetCount += 1;
} else {
w[i] &= !m;
e[i] &= !m;
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions test/c/makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
all: std server client server_conn client_conn unixcli unixsrv socketpair stat dev fork signal futex multithread epoll mkdir fifo timerfd eventfd seek gettimeofday server_benchmark client_benchmark epoll_client epoll_server multithread_client multithread_server multithread_pp_client multithread_pp_server poll udpcli udpsrv udpclidual udpsrvdual
all: std server client server_conn client_conn unixcli unixsrv socketpair stat dev fork signal futex multithread epoll mkdir fifo timerfd eventfd seek gettimeofday server_benchmark client_benchmark epoll_client epoll_server multithread_client multithread_server multithread_pp_client multithread_pp_server poll select_except_connect udpcli udpsrv udpclidual udpsrvdual

std: std.c
gcc -o std std.c
dnstest: dnstest.c
gcc -o dnstest dnstest.c
poll: poll.c
gcc -o poll poll.c
select_except_connect: select_except_connect.c
gcc -Wall -Wextra -o select_except_connect select_except_connect.c
server: server.c
gcc -o server server.c
client: client.c
Expand Down Expand Up @@ -79,4 +81,4 @@ udpclidual: udpclidual.c
udpsrvdual: udpsrvdual.c
gcc -o udpsrvdual udpsrvdual.c
clean:
rm std server client unixcli unixsrv socketpair stat dev fork signal futex multithread epoll mkdir fifo timerfd eventfd seek gettimeofday
rm -f std server client select_except_connect unixcli unixsrv socketpair stat dev fork signal futex multithread epoll mkdir fifo timerfd eventfd seek gettimeofday
141 changes: 141 additions & 0 deletions test/c/select_except_connect.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// Copyright (c) 2026 Quark Container Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>

static void fail(const char *msg)
{
perror(msg);
exit(1);
}

int main(void)
{
int listener = socket(AF_INET, SOCK_STREAM, 0);
if (listener < 0) {
fail("socket(listener)");
}

int one = 1;
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
fail("setsockopt(SO_REUSEADDR)");
}

struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = 0;

if (bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
fail("bind(listener)");
}
if (listen(listener, 1) < 0) {
fail("listen(listener)");
}

socklen_t addr_len = sizeof(addr);
if (getsockname(listener, (struct sockaddr *)&addr, &addr_len) < 0) {
fail("getsockname(listener)");
}

pid_t child = fork();
if (child < 0) {
fail("fork");
}
if (child == 0) {
int accepted = accept(listener, NULL, NULL);
if (accepted < 0) {
fail("accept");
}
char byte;
(void)read(accepted, &byte, sizeof(byte));
close(accepted);
close(listener);
return 0;
}

int client = socket(AF_INET, SOCK_STREAM, 0);
if (client < 0) {
fail("socket(client)");
}
int flags = fcntl(client, F_GETFL, 0);
if (flags < 0 || fcntl(client, F_SETFL, flags | O_NONBLOCK) < 0) {
fail("fcntl(O_NONBLOCK)");
}

int rc = connect(client, (struct sockaddr *)&addr, sizeof(addr));
if (rc < 0 && errno != EINPROGRESS) {
fail("connect(client)");
}

fd_set readfds;
fd_set writefds;
fd_set exceptfds;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
FD_SET(client, &readfds);
FD_SET(client, &writefds);
FD_SET(client, &exceptfds);

struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
rc = select(client + 1, &readfds, &writefds, &exceptfds, &timeout);
if (rc < 0) {
fail("select");
}
if (rc == 0) {
fprintf(stderr, "select timed out\n");
return 1;
}

int err = 0;
socklen_t err_len = sizeof(err);
if (getsockopt(client, SOL_SOCKET, SO_ERROR, &err, &err_len) < 0) {
fail("getsockopt(SO_ERROR)");
}

printf("select rc=%d read=%d write=%d except=%d so_error=%d\n",
rc,
FD_ISSET(client, &readfds) != 0,
FD_ISSET(client, &writefds) != 0,
FD_ISSET(client, &exceptfds) != 0,
err);

if (err != 0) {
fprintf(stderr, "SO_ERROR=%d (%s)\n", err, strerror(err));
return 1;
}
if (!FD_ISSET(client, &writefds)) {
fprintf(stderr, "client socket was not in writefds\n");
return 1;
}
if (FD_ISSET(client, &exceptfds)) {
fprintf(stderr, "client socket was incorrectly left in exceptfds\n");
return 1;
}

(void)write(client, "x", 1);
close(client);
close(listener);

int status = 0;
if (waitpid(child, &status, 0) < 0) {
fail("waitpid");
}
return status == 0 ? 0 : 1;
}