int asynchronous_close(int fd) { int r; /* This is supposed to behave similar to safe_close(), but * actually invoke close() asynchronously, so that it will * never block. Ideally the kernel would have an API for this, * but it doesn't, so we work around it, and hide this as a * far away as we can. */ if (fd >= 0) { PROTECT_ERRNO; r = asynchronous_job(close_thread, FD_TO_PTR(fd)); if (r < 0) assert_se(close_nointr(fd) != -EBADF); } return -1; }
int main(int argc, char *argv[]) { int fd; char name[] = "/tmp/test-asynchronous_close.XXXXXX"; fd = mkostemp_safe(name); assert_se(fd >= 0); asynchronous_close(fd); assert_se(asynchronous_job(async_func, NULL) >= 0); assert_se(asynchronous_sync(NULL) >= 0); sleep(1); assert_se(fcntl(fd, F_GETFD) == -1); assert_se(test_async); unlink(name); return 0; }
int asynchronous_sync(void) { log_debug("Spawning new thread for sync"); return asynchronous_job(sync_thread, NULL); }
static void test_nameinfo_pretty(void) { _cleanup_free_ char *stdin_name = NULL, *localhost = NULL; union sockaddr_union s = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(INADDR_ANY), }; int r; union sockaddr_union c = {}; socklen_t slen = sizeof(c.in), clen = sizeof(c.in); _cleanup_close_ int sfd = -1, cfd = -1; r = getnameinfo_pretty(STDIN_FILENO, &stdin_name); log_info_errno(r, "No connection remote: %m"); assert_se(r < 0); sfd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0); assert_se(sfd >= 0); assert_se(bind(sfd, &s.sa, sizeof(s.in)) == 0); /* find out the port number */ assert_se(getsockname(sfd, &s.sa, &slen) == 0); assert_se(listen(sfd, 1) == 0); assert_se(asynchronous_job(connect_thread, &s) == 0); log_debug("Accepting new connection on fd:%d", sfd); cfd = accept4(sfd, &c.sa, &clen, SOCK_CLOEXEC); assert_se(cfd >= 0); r = getnameinfo_pretty(cfd, &localhost); log_info("Connection from %s", localhost); assert_se(r == 0); } static void test_sockaddr_equal(void) { union sockaddr_union a = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(INADDR_ANY), }; union sockaddr_union b = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(INADDR_ANY), }; union sockaddr_union c = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(1234), }; union sockaddr_union d = { .in6.sin6_family = AF_INET6, .in6.sin6_port = 0, .in6.sin6_addr = IN6ADDR_ANY_INIT, }; assert_se(sockaddr_equal(&a, &a)); assert_se(sockaddr_equal(&a, &b)); assert_se(sockaddr_equal(&d, &d)); assert_se(!sockaddr_equal(&a, &c)); assert_se(!sockaddr_equal(&b, &c)); } int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); test_socket_address_parse(); test_socket_address_parse_netlink(); test_socket_address_equal(); test_socket_address_get_path(); test_socket_address_is(); test_socket_address_is_netlink(); test_in_addr_is_null(); test_in_addr_prefix_intersect(); test_in_addr_prefix_next(); test_in_addr_to_string(); test_nameinfo_pretty(); test_sockaddr_equal(); return 0; }