v->server = sd_varlink_server_ref(server);
sd_varlink_ref(v);
+ if (ucred_acquired)
+ json_stream_set_peer_ucred(&v->stream, &ucred);
+
r = json_stream_attach_fds(&v->stream, input_fd, output_fd);
- if (r < 0)
+ if (r < 0) {
+ sd_varlink_close(v);
return r;
+ }
if (server->flags & SD_VARLINK_SERVER_INHERIT_USERDATA)
v->userdata = server->userdata;
if (FLAGS_SET(server->flags, SD_VARLINK_SERVER_UPGRADABLE))
json_stream_set_flags(&v->stream, JSON_STREAM_BOUNDED_READS, true);
- if (ucred_acquired)
- json_stream_set_peer_ucred(&v->stream, &ucred);
-
_cleanup_free_ char *desc = NULL;
if (asprintf(&desc, "%s-%i-%i", varlink_server_description(server), input_fd, output_fd) >= 0)
json_stream_set_description(&v->stream, desc);
ASSERT_OK(r);
}
+TEST(add_connection_failure_cleanup) {
+ _cleanup_(sd_varlink_server_unrefp) sd_varlink_server *s = NULL;
+ _cleanup_close_pair_ int fds[2] = EBADF_PAIR;
+ const struct ucred ucred = {
+ .pid = getpid(),
+ .uid = getuid(),
+ .gid = getgid(),
+ };
+
+ ASSERT_OK(sd_varlink_server_new(&s, SD_VARLINK_SERVER_ACCOUNT_UID));
+ ASSERT_OK(sd_varlink_server_set_connections_per_uid_max(s, 1));
+ ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds));
+
+ int bad_fd = ASSERT_OK(memfd_new("closed-fd"));
+ ASSERT_OK_ERRNO(close(bad_fd));
+
+ ASSERT_ERROR(sd_varlink_server_add_connection_pair(s, fds[0], bad_fd, &ucred, /* ret= */ NULL), EBADF);
+ ASSERT_EQ(sd_varlink_server_current_connections(s), 0U);
+
+ sd_varlink *v = NULL;
+ ASSERT_OK(sd_varlink_server_add_connection(s, fds[0], &v));
+ TAKE_FD(fds[0]);
+ ASSERT_NOT_NULL(v);
+ ASSERT_EQ(sd_varlink_server_current_connections(s), 1U);
+
+ ASSERT_OK_POSITIVE(sd_varlink_close(v));
+ ASSERT_EQ(sd_varlink_server_current_connections(s), 0U);
+}
+
DEFINE_TEST_MAIN(LOG_DEBUG);