if (v->state == VARLINK_PROCESSING_METHOD) {
r = sd_varlink_error(v, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
- if (r < 0)
+ /* If we didn't manage to enqueue an error response, then fail the
+ * connection completely. Otherwise ignore the error from
+ * sd_varlink_error() here, as it is synthesized from the function's
+ * parameters. */
+ if (r < 0 && VARLINK_STATE_WANTS_REPLY(v->state))
goto fail;
}
} else if (r < 0) {
if (VARLINK_STATE_WANTS_REPLY(v->state)) {
r = sd_varlink_error_invalid_parameter_name(v, bad_field);
- if (r < 0)
+ /* If we didn't manage to enqueue an error response, then fail the connection completely. */
+ if (r < 0 && VARLINK_STATE_WANTS_REPLY(v->state))
goto fail;
}
}
* method call remains unanswered. */
if (VARLINK_STATE_WANTS_REPLY(v->state)) {
r = sd_varlink_error_errno(v, r);
- if (r < 0)
+ /* If we didn't manage to enqueue an error response, then fail the connection completely. */
+ if (r < 0 && VARLINK_STATE_WANTS_REPLY(v->state))
goto fail;
}
}
}
} else if (VARLINK_STATE_WANTS_REPLY(v->state)) {
r = sd_varlink_errorbo(v, SD_VARLINK_ERROR_METHOD_NOT_FOUND, SD_JSON_BUILD_PAIR("method", SD_JSON_BUILD_STRING(method)));
- if (r < 0)
+ /* If we didn't manage to enqueue an error response, then fail the connection completely. */
+ if (r < 0 && VARLINK_STATE_WANTS_REPLY(v->state))
goto fail;
}
} else
varlink_set_state(v, VARLINK_PROCESSED_METHOD);
- return 1;
+ /* Everything worked. Let's now return the error we got passed as input as negative errno, so that
+ * programs can just do "return sd_varlink_error();" and get both: a friendly error reply to clients,
+ * and an error return from the current stack frame. */
+ return sd_varlink_error_to_errno(error_id, parameters);
}
_public_ int sd_varlink_errorb(sd_varlink *v, const char *error_id, ...) {
int r;
a = sd_json_variant_by_key(parameters, "a");
- if (!a)
- return sd_varlink_error(link, "io.test.BadParameters", NULL);
+ if (!a) {
+ r = sd_varlink_error(link, "io.test.BadParameters", NULL);
+ assert_se(r == -EBADR);
+ return r;
+ }
x = sd_json_variant_integer(a);
b = sd_json_variant_by_key(parameters, "b");
- if (!b)
- return sd_varlink_error(link, "io.test.BadParameters", NULL);
+ if (!b) {
+ r = sd_varlink_error(link, "io.test.BadParameters", NULL);
+ assert_se(r == -EBADR);
+ return r;
+ }
y = sd_json_variant_integer(b);
int r;
a = sd_json_variant_by_key(parameters, "fd");
- if (!a)
- return sd_varlink_error(link, "io.test.BadParameters", NULL);
+ if (!a) {
+ r = sd_varlink_error_invalid_parameter_name(link, "fd");
+ assert_se(r == -EINVAL);
+ return r;
+ }
ASSERT_STREQ(sd_json_variant_string(a), "whoop");
_cleanup_(sd_json_variant_unrefp) sd_json_variant *i = NULL;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *wrong = NULL;
sd_json_variant *o = NULL, *k = NULL, *j = NULL;
- const char *error_id;
- const char *e;
+ const char *error_id, *e;
int x = 0;
assert_se(sd_json_build(&i, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(88)),
assert_se(sd_varlink_push_fd(c, fd3) == 2);
assert_se(sd_varlink_callb(c, "io.test.PassFD", &o, &e, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("fd", SD_JSON_BUILD_STRING("whoop")))) >= 0);
+ assert_se(!e);
int fd4 = sd_varlink_peek_fd(c, 0);
int fd5 = sd_varlink_peek_fd(c, 1);
test_fd(fd4, "miau", 4);
test_fd(fd5, "wuff", 4);
+ assert_se(sd_varlink_callb(c, "io.test.PassFD", &o, &e, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("fdx", SD_JSON_BUILD_STRING("whoopx")))) >= 0);
+ ASSERT_TRUE(sd_varlink_error_is_invalid_parameter(e, o, "fd"));
+
assert_se(sd_varlink_callb(c, "io.test.IDontExist", &o, &e, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("x", SD_JSON_BUILD_REAL(5.5)))) >= 0);
ASSERT_STREQ(sd_json_variant_string(sd_json_variant_by_key(o, "method")), "io.test.IDontExist");
ASSERT_STREQ(e, SD_VARLINK_ERROR_METHOD_NOT_FOUND);