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 stderr_fd;
|
||||
|
||||
int exit_status;
|
||||
int is_exited;
|
||||
int pid;
|
||||
int is_blocked;
|
||||
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].stdout_fd = stdout_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].is_blocked = 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();
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
char buf[len];
|
||||
@ -243,8 +259,8 @@ void handle_input(int client_id, int len)
|
||||
|
||||
if (len == 0) {
|
||||
if (client_info[client_id].is_blocked)
|
||||
client_info[client_id].
|
||||
is_close_after_flush_needed = 1;
|
||||
client_info[client_id].is_close_after_flush_needed
|
||||
= 1;
|
||||
else {
|
||||
close(client_info[client_id].stdin_fd);
|
||||
client_info[client_id].stdin_fd = -1;
|
||||
@ -339,11 +355,18 @@ void handle_process_data(int fd)
|
||||
write_all_vchan_ext(buf, ret);
|
||||
}
|
||||
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].client_id = -1;
|
||||
process_fd[fd].is_blocked = 0;
|
||||
close(fd);
|
||||
update_max_process_fd();
|
||||
possibly_remove_process(client_id);
|
||||
}
|
||||
if (ret < 0)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
int status;
|
||||
@ -418,8 +408,9 @@ void reap_children()
|
||||
client_id = find_info(pid);
|
||||
if (client_id < 0)
|
||||
continue;
|
||||
flush_out_err(client_id);
|
||||
remove_process(client_id, status);
|
||||
client_info[client_id].is_exited = 1;
|
||||
client_info[client_id].exit_status = status;
|
||||
possibly_remove_process(client_id);
|
||||
}
|
||||
child_exited = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user