Merge branch 'syncjoanna' of git.qubes-os.org:/var/lib/qubes/git/rafal/core into r1-beta1
This commit is contained in:
commit
1bf125fc63
@ -51,6 +51,8 @@ struct _client_info {
|
|||||||
int stdout_fd;
|
int stdout_fd;
|
||||||
int stderr_fd;
|
int stderr_fd;
|
||||||
|
|
||||||
|
int exit_status;
|
||||||
|
int is_exited;
|
||||||
int pid;
|
int pid;
|
||||||
int is_blocked;
|
int is_blocked;
|
||||||
int is_close_after_flush_needed;
|
int is_close_after_flush_needed;
|
||||||
@ -169,6 +171,8 @@ void handle_exec(int client_id, int len)
|
|||||||
client_info[client_id].stdin_fd = stdin_fd;
|
client_info[client_id].stdin_fd = stdin_fd;
|
||||||
client_info[client_id].stdout_fd = stdout_fd;
|
client_info[client_id].stdout_fd = stdout_fd;
|
||||||
client_info[client_id].stderr_fd = stderr_fd;
|
client_info[client_id].stderr_fd = stderr_fd;
|
||||||
|
client_info[client_id].exit_status = 0;
|
||||||
|
client_info[client_id].is_exited = 0;
|
||||||
client_info[client_id].pid = pid;
|
client_info[client_id].pid = pid;
|
||||||
client_info[client_id].is_blocked = 0;
|
client_info[client_id].is_blocked = 0;
|
||||||
client_info[client_id].is_close_after_flush_needed = 0;
|
client_info[client_id].is_close_after_flush_needed = 0;
|
||||||
@ -233,6 +237,18 @@ void remove_process(int client_id, int status)
|
|||||||
update_max_process_fd();
|
update_max_process_fd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove process not immediately after it has exited, but after its stdout and stderr has been drained
|
||||||
|
// previous method implemented in flush_out_err was broken - it cannot work when peer signalled it is blocked
|
||||||
|
void possibly_remove_process(int client_id)
|
||||||
|
{
|
||||||
|
if (client_info[client_id].stdout_fd == -1 &&
|
||||||
|
client_info[client_id].stderr_fd == -1 &&
|
||||||
|
client_info[client_id].is_exited)
|
||||||
|
remove_process(client_id,
|
||||||
|
client_info[client_id].exit_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void handle_input(int client_id, int len)
|
void handle_input(int client_id, int len)
|
||||||
{
|
{
|
||||||
char buf[len];
|
char buf[len];
|
||||||
@ -243,8 +259,8 @@ void handle_input(int client_id, int len)
|
|||||||
|
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
if (client_info[client_id].is_blocked)
|
if (client_info[client_id].is_blocked)
|
||||||
client_info[client_id].
|
client_info[client_id].is_close_after_flush_needed
|
||||||
is_close_after_flush_needed = 1;
|
= 1;
|
||||||
else {
|
else {
|
||||||
close(client_info[client_id].stdin_fd);
|
close(client_info[client_id].stdin_fd);
|
||||||
client_info[client_id].stdin_fd = -1;
|
client_info[client_id].stdin_fd = -1;
|
||||||
@ -339,11 +355,18 @@ void handle_process_data(int fd)
|
|||||||
write_all_vchan_ext(buf, ret);
|
write_all_vchan_ext(buf, ret);
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
int client_id = process_fd[fd].client_id;
|
||||||
|
if (process_fd[fd].type == FDTYPE_STDOUT)
|
||||||
|
client_info[client_id].stdout_fd = -1;
|
||||||
|
else
|
||||||
|
client_info[client_id].stderr_fd = -1;
|
||||||
|
|
||||||
process_fd[fd].type = FDTYPE_INVALID;
|
process_fd[fd].type = FDTYPE_INVALID;
|
||||||
process_fd[fd].client_id = -1;
|
process_fd[fd].client_id = -1;
|
||||||
process_fd[fd].is_blocked = 0;
|
process_fd[fd].is_blocked = 0;
|
||||||
close(fd);
|
close(fd);
|
||||||
update_max_process_fd();
|
update_max_process_fd();
|
||||||
|
possibly_remove_process(client_id);
|
||||||
}
|
}
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
remove_process(process_fd[fd].client_id, 127);
|
remove_process(process_fd[fd].client_id, 127);
|
||||||
@ -376,39 +399,6 @@ void handle_process_data_all(fd_set * select_fds)
|
|||||||
handle_process_data(i);
|
handle_process_data(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void flush_out_err(int client_id)
|
|
||||||
{
|
|
||||||
fd_set select_set;
|
|
||||||
int fd_max = -1;
|
|
||||||
int i;
|
|
||||||
int ret;
|
|
||||||
struct timeval tv;
|
|
||||||
for (;;) {
|
|
||||||
FD_ZERO(&select_set);
|
|
||||||
for (i = 0; i <= max_process_fd; i++) {
|
|
||||||
if (process_fd[i].type != FDTYPE_INVALID
|
|
||||||
&& !process_fd[i].is_blocked
|
|
||||||
&& process_fd[i].client_id == client_id) {
|
|
||||||
FD_SET(i, &select_set);
|
|
||||||
fd_max = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fd_max == -1)
|
|
||||||
return;
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
ret = select(fd_max + 1, &select_set, NULL, NULL, &tv);
|
|
||||||
if (ret < 0 && errno != EINTR) {
|
|
||||||
perror("select");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (!ret)
|
|
||||||
return;
|
|
||||||
handle_process_data_all(&select_set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void reap_children()
|
void reap_children()
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
@ -418,8 +408,9 @@ void reap_children()
|
|||||||
client_id = find_info(pid);
|
client_id = find_info(pid);
|
||||||
if (client_id < 0)
|
if (client_id < 0)
|
||||||
continue;
|
continue;
|
||||||
flush_out_err(client_id);
|
client_info[client_id].is_exited = 1;
|
||||||
remove_process(client_id, status);
|
client_info[client_id].exit_status = status;
|
||||||
|
possibly_remove_process(client_id);
|
||||||
}
|
}
|
||||||
child_exited = 0;
|
child_exited = 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user