audiod_command.c contains this comment:
/*
* command handlers don't close their fd on errors (ret < 0) so that
* its caller can send an error message. Otherwise (ret >= 0) it's up
* to each individual command to close the fd if necessary.
*/
This is a somewhat weird rule and this commit gets rid of it. Instead,
from now on the command handlers must not close their file descriptor
and handle_connect() closes it unconditionally.
The grab and stat commands need special treatment, which was the reason
for imposing the above rule. They need to keep the file descriptor open
to send the status items or the grabbed stream to the client. This
patch makes these two handlers create a copy of the descriptor with
dup(2). The new approach is simpler and less error-prone.
static int stat_client_add(int fd, uint64_t mask, int parser_friendly)
{
struct stat_client *new_client;
static int stat_client_add(int fd, uint64_t mask, int parser_friendly)
{
struct stat_client *new_client;
if (num_clients >= MAX_STAT_CLIENTS) {
PARA_ERROR_LOG("maximal number of stat clients (%d) exceeded\n",
MAX_STAT_CLIENTS);
return -E_TOO_MANY_CLIENTS;
}
if (num_clients >= MAX_STAT_CLIENTS) {
PARA_ERROR_LOG("maximal number of stat clients (%d) exceeded\n",
MAX_STAT_CLIENTS);
return -E_TOO_MANY_CLIENTS;
}
- PARA_INFO_LOG("adding client on fd %d\n", fd);
- new_client = para_calloc(sizeof(struct stat_client));
- new_client->fd = fd;
+ ret = dup(fd);
+ if (ret < 0)
+ return -ERRNO_TO_PARA_ERROR(errno);
+ new_client = para_calloc(sizeof(*new_client));
+ new_client->fd = ret;
+ PARA_INFO_LOG("adding client on fd %d\n", new_client->fd);
new_client->item_mask = mask;
if (parser_friendly)
new_client->flags = SCF_PARSER_FRIENDLY;
new_client->item_mask = mask;
if (parser_friendly)
new_client->flags = SCF_PARSER_FRIENDLY;
-/*
- * command handlers don't close their fd on errors (ret < 0) so that
- * its caller can send an error message. Otherwise (ret >= 0) it's up
- * to each individual command to close the fd if necessary.
- */
-
static int com_help(int fd, int argc, char **argv)
{
int i, ret;
char *buf;
const char *dflt = "No such command. Available commands:\n";
static int com_help(int fd, int argc, char **argv)
{
int i, ret;
char *buf;
const char *dflt = "No such command. Available commands:\n";
- if (argc < 2) {
- ret = dump_commands(fd);
- goto out;
- }
+ if (argc < 2)
+ return dump_commands(fd);
FOR_EACH_COMMAND(i) {
if (strcmp(audiod_cmds[i].name, argv[1]))
continue;
FOR_EACH_COMMAND(i) {
if (strcmp(audiod_cmds[i].name, argv[1]))
continue;
);
ret = client_write(fd, buf);
free(buf);
);
ret = client_write(fd, buf);
free(buf);
}
ret = client_write(fd, dflt);
if (ret > 0)
ret = dump_commands(fd);
}
ret = client_write(fd, dflt);
if (ret > 0)
ret = dump_commands(fd);
-out:
- if (ret >= 0)
- close(fd);
if (tl)
ret = client_write(fd, tl);
free(tl);
if (tl)
ret = client_write(fd, tl);
free(tl);
- if (ret > 0)
- close(fd);
return grab_client_new(fd, argc, argv, &sched);
}
return grab_client_new(fd, argc, argv, &sched);
}
-static int com_term(int fd, __a_unused int argc, __a_unused char **argv)
+static int com_term(__a_unused int fd, __a_unused int argc, __a_unused char **argv)
-static int com_on(int fd, __a_unused int argc, __a_unused char **argv)
+static int com_on(__a_unused int fd, __a_unused int argc, __a_unused char **argv)
{
audiod_status = AUDIOD_ON;
{
audiod_status = AUDIOD_ON;
-static int com_off(int fd, __a_unused int argc, __a_unused char **argv)
+static int com_off(__a_unused int fd, __a_unused int argc, __a_unused char **argv)
{
audiod_status = AUDIOD_OFF;
{
audiod_status = AUDIOD_OFF;
-static int com_sb(int fd, __a_unused int argc, __a_unused char **argv)
+static int com_sb(__a_unused int fd, __a_unused int argc, __a_unused char **argv)
{
audiod_status = AUDIOD_STANDBY;
{
audiod_status = AUDIOD_STANDBY;
-static int com_cycle(int fd, int argc, char **argv)
+static int com_cycle(__a_unused int fd, int argc, char **argv)
{
switch (audiod_status) {
case AUDIOD_ON:
{
switch (audiod_status) {
case AUDIOD_ON:
return com_off(fd, argc, argv);
break;
}
return com_off(fd, argc, argv);
break;
}
msg = make_message("%s\n", version_single_line("audiod"));
ret = client_write(fd, msg);
free(msg);
msg = make_message("%s\n", version_single_line("audiod"));
ret = client_write(fd, msg);
free(msg);
- if (ret >= 0)
- close(fd);
ret = -E_INVALID_AUDIOD_CMD;
out:
free_argv(argv);
ret = -E_INVALID_AUDIOD_CMD;
out:
free_argv(argv);
- if (clifd > 0 && ret < 0 && ret != -E_CLIENT_WRITE) {
+ if (ret < 0 && ret != -E_CLIENT_WRITE) {
char *tmp = make_message("%s\n", para_strerror(-ret));
client_write(clifd, tmp);
free(tmp);
char *tmp = make_message("%s\n", para_strerror(-ret));
client_write(clifd, tmp);
free(tmp);
ret = gc_check_args(argc, argv, gc);
if (ret < 0)
goto err_out;
ret = gc_check_args(argc, argv, gc);
if (ret < 0)
goto err_out;
+ ret = dup(fd);
+ if (ret < 0) {
+ ret = -ERRNO_TO_PARA_ERROR(errno);
+ goto err_out;
+ }
+ gc->fd = ret;
para_list_add(&gc->node, &inactive_grab_client_list);
gc_activate(gc, s);
return 1;
para_list_add(&gc->node, &inactive_grab_client_list);
gc_activate(gc, s);
return 1;