mirror of
https://github.com/systemd/systemd.git
synced 2026-11-06 05:17:24 +00:00
varlink-util: add varlink_execute_directory() flavour that returns unconnectable sockets
This commit is contained in:
1 parent
8948eb15d9
commit
e878354562
3 files changed
+62
-4
No files matched your search
@@ -21,6 +21,7 @@
|
||||
#include "rm-rf.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
#include "time-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
@@ -1515,6 +1516,20 @@ static int execute_dir_client_fiber(void *arg) {
|
||||
a->reply_count), (ssize_t) a->n_servers);
|
||||
ASSERT_EQ(*a->reply_count, a->n_servers);
|
||||
|
||||
/* Sockets that have a live listener must be counted as contacted, not as offline. */
|
||||
_cleanup_strv_free_ char **offline = NULL;
|
||||
ASSERT_OK_EQ(varlink_execute_directory_full(
|
||||
a->tmpdir,
|
||||
"io.test.ExecDirPing",
|
||||
/* parameters= */ NULL,
|
||||
/* more= */ false,
|
||||
/* timeout_usec= */ USEC_INFINITY,
|
||||
execute_dir_reply,
|
||||
a->reply_count,
|
||||
&offline), (ssize_t) a->n_servers);
|
||||
ASSERT_TRUE(strv_isempty(offline));
|
||||
ASSERT_EQ(*a->reply_count, 2 * a->n_servers);
|
||||
|
||||
/* Calling the helper against a non-existent directory must fail. */
|
||||
_cleanup_free_ char *nope = NULL;
|
||||
ASSERT_OK(asprintf(&nope, "%s/does-not-exist", a->tmpdir));
|
||||
@@ -1542,6 +1557,33 @@ static int execute_dir_client_fiber(void *arg) {
|
||||
a->reply_count));
|
||||
ASSERT_EQ(*a->reply_count, count_before);
|
||||
|
||||
ASSERT_OK_ZERO(varlink_execute_directory_full(
|
||||
empty,
|
||||
"io.test.ExecDirPing",
|
||||
/* parameters= */ NULL,
|
||||
/* more= */ false,
|
||||
/* timeout_usec= */ USEC_INFINITY,
|
||||
execute_dir_reply,
|
||||
a->reply_count,
|
||||
&offline));
|
||||
ASSERT_TRUE(strv_isempty(offline));
|
||||
|
||||
/* A socket inode nobody listens on must not be counted as contacted, but as offline. */
|
||||
_cleanup_free_ char *dead = ASSERT_PTR(path_join(empty, "dead"));
|
||||
ASSERT_OK_ERRNO(mknod(dead, S_IFSOCK|0600, 0));
|
||||
|
||||
ASSERT_OK_ZERO(varlink_execute_directory_full(
|
||||
empty,
|
||||
"io.test.ExecDirPing",
|
||||
/* parameters= */ NULL,
|
||||
/* more= */ false,
|
||||
/* timeout_usec= */ USEC_INFINITY,
|
||||
execute_dir_reply,
|
||||
a->reply_count,
|
||||
&offline));
|
||||
ASSERT_TRUE(strv_equal(offline, STRV_MAKE("dead")));
|
||||
ASSERT_EQ(*a->reply_count, count_before);
|
||||
|
||||
ASSERT_OK(sd_event_exit(sd_fiber_get_event(), EXIT_SUCCESS));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "set.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "varlink-internal.h"
|
||||
#include "varlink-util.h"
|
||||
#include "version.h"
|
||||
@@ -245,14 +246,15 @@ static int varlink_finish_idle(Set *s) {
|
||||
|
||||
#define VARLINK_EXECUTE_SOCKETS_MAX 255
|
||||
|
||||
ssize_t varlink_execute_directory(
|
||||
ssize_t varlink_execute_directory_full(
|
||||
const char *path,
|
||||
const char *method,
|
||||
sd_json_variant *parameters,
|
||||
bool more,
|
||||
usec_t timeout_usec,
|
||||
sd_varlink_reply_t reply,
|
||||
void *userdata) {
|
||||
void *userdata,
|
||||
char ***ret_offline_sockets) {
|
||||
|
||||
int r;
|
||||
|
||||
@@ -262,7 +264,10 @@ ssize_t varlink_execute_directory(
|
||||
/* Invokes the specified method on all Varlink sockets in the specified directory. Any reply
|
||||
* will be dispatched to the reply callback. Blocks until the last reply has come in.
|
||||
*
|
||||
* Returns how many sockets were contacted.
|
||||
* Returns how many sockets were contacted. If ret_offline_sockets is non-NULL it is set to the
|
||||
* names of the sockets that exist in the directory but could not be contacted (because nobody
|
||||
* listens on them, or because there are too many of them). This allows callers to distinguish
|
||||
* "nobody there" from "somebody there, but not reachable".
|
||||
*
|
||||
* Usecase for all of this: hook directories, where components can link their sockets into to get
|
||||
* notified about certain system events. */
|
||||
@@ -278,6 +283,7 @@ ssize_t varlink_execute_directory(
|
||||
|
||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||
_cleanup_(set_freep) Set *links = NULL;
|
||||
_cleanup_strv_free_ char **offline = NULL;
|
||||
size_t t = 0;
|
||||
FOREACH_ARRAY(dp, dentries->entries, dentries->n_entries) {
|
||||
struct dirent *de = *dp;
|
||||
@@ -290,6 +296,8 @@ ssize_t varlink_execute_directory(
|
||||
|
||||
if (set_size(links) >= VARLINK_EXECUTE_SOCKETS_MAX) {
|
||||
log_debug("Too many sockets (%zu) in directory, skipping '%s'.", t, j);
|
||||
if (ret_offline_sockets && strv_extend(&offline, de->d_name) < 0)
|
||||
return log_oom_debug();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -300,6 +308,8 @@ ssize_t varlink_execute_directory(
|
||||
r = connect_unix_path(socket_fd, fd, de->d_name);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to connect to '%s', ignoring: %m", j);
|
||||
if (ret_offline_sockets && strv_extend(&offline, de->d_name) < 0)
|
||||
return log_oom_debug();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -377,5 +387,8 @@ ssize_t varlink_execute_directory(
|
||||
return r;
|
||||
}
|
||||
|
||||
if (ret_offline_sockets)
|
||||
*ret_offline_sockets = TAKE_PTR(offline);
|
||||
|
||||
return (ssize_t) c;
|
||||
}
|
||||
@@ -34,4 +34,7 @@ int varlink_check_privileged_peer(sd_varlink *vl);
|
||||
|
||||
extern const struct hash_ops varlink_hash_ops;
|
||||
|
||||
ssize_t varlink_execute_directory(const char *path, const char *method, sd_json_variant *parameters, bool more, usec_t timeout_usec, sd_varlink_reply_t reply, void *userdata);
|
||||
ssize_t varlink_execute_directory_full(const char *path, const char *method, sd_json_variant *parameters, bool more, usec_t timeout_usec, sd_varlink_reply_t reply, void *userdata, char ***ret_offline_sockets);
|
||||
static inline ssize_t varlink_execute_directory(const char *path, const char *method, sd_json_variant *parameters, bool more, usec_t timeout_usec, sd_varlink_reply_t reply, void *userdata) {
|
||||
return varlink_execute_directory_full(path, method, parameters, more, timeout_usec, reply, userdata, /* ret_offline_sockets= */ NULL);
|
||||
}
|
||||
Reference in new issue
Block a user