qrexec: when forgetting about a client/process, flush buffered data
We need to spawn a child to take care of buffered data flushing, if there is any. Expensive, but should be needed rarely.
This commit is contained in:
parent
53b517f6a5
commit
1d24ef9d1a
@ -6,8 +6,8 @@ COMMONIOALL=../common/ioall.o
|
||||
all: qrexec_daemon qrexec_agent qrexec_client
|
||||
qrexec_daemon: qrexec_daemon.o unix_server.o $(COMMONIOALL) txrx-vchan.o buffer.o write_stdin.o
|
||||
$(CC) -g -o qrexec_daemon qrexec_daemon.o unix_server.o $(COMMONIOALL) txrx-vchan.o write_stdin.o buffer.o $(XENLIBS)
|
||||
qrexec_agent: qrexec_agent.o exec.o txrx-vchan.o write_stdin.o buffer.o
|
||||
$(CC) -g -o qrexec_agent qrexec_agent.o exec.o txrx-vchan.o write_stdin.o buffer.o $(XENLIBS)
|
||||
qrexec_agent: qrexec_agent.o exec.o txrx-vchan.o write_stdin.o buffer.o $(COMMONIOALL)
|
||||
$(CC) -g -o qrexec_agent qrexec_agent.o exec.o txrx-vchan.o write_stdin.o buffer.o $(COMMONIOALL) $(XENLIBS)
|
||||
qrexec_client: qrexec_client.o $(COMMONIOALL) exec.o
|
||||
$(CC) -g -o qrexec_client qrexec_client.o $(COMMONIOALL) exec.o
|
||||
clean:
|
||||
|
@ -45,3 +45,4 @@ int flush_client_data(int fd, int clid, struct buffer *buffer);
|
||||
int write_stdin(int fd, int clid, char *data, int len,
|
||||
struct buffer *buffer);
|
||||
void set_nonblock(int fd);
|
||||
int fork_and_flush_stdin(int fd, struct buffer *buffer);
|
||||
|
@ -206,8 +206,11 @@ void remove_process(int clid, int status)
|
||||
int i;
|
||||
if (!client_info[clid].pid)
|
||||
return;
|
||||
fork_and_flush_stdin(client_info[clid].stdin_fd, &client_info[clid].buffer);
|
||||
#if 0
|
||||
// let's let it die by itself, possibly after it has received buffered stdin
|
||||
kill(client_info[clid].pid, SIGKILL);
|
||||
|
||||
#endif
|
||||
if (status != -1)
|
||||
send_exit_code(clid, status);
|
||||
|
||||
|
@ -118,10 +118,15 @@ void handle_new_client()
|
||||
max_client_fd = fd;
|
||||
}
|
||||
|
||||
int children_count;
|
||||
|
||||
void flush_client(int fd)
|
||||
{
|
||||
int i;
|
||||
struct server_header s_hdr;
|
||||
|
||||
if (fork_and_flush_stdin(fd, &clients[fd].buffer))
|
||||
children_count++;
|
||||
close(fd);
|
||||
clients[fd].state = CLIENT_INVALID;
|
||||
buffer_free(&clients[fd].buffer);
|
||||
@ -249,7 +254,6 @@ void pass_to_client(int clid, struct client_header *hdr)
|
||||
}
|
||||
}
|
||||
|
||||
int children_count;
|
||||
int child_exited;
|
||||
|
||||
void sigchld_handler(int x)
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <ioall.h>
|
||||
#include <stdlib.h>
|
||||
#include "qrexec.h"
|
||||
#include "buffer.h"
|
||||
#include "glue.h"
|
||||
@ -66,7 +68,7 @@ int write_stdin(int fd, int clid, char *data, int len,
|
||||
buffer_append(buffer, data, len);
|
||||
return WRITE_STDIN_BUFFERED;
|
||||
}
|
||||
|
||||
|
||||
ret = write(fd, data, len);
|
||||
if (ret == len)
|
||||
return WRITE_STDIN_OK;
|
||||
@ -96,3 +98,31 @@ void set_nonblock(int fd)
|
||||
int fl = fcntl(fd, F_GETFL, 0);
|
||||
fcntl(fd, F_SETFL, fl | O_NONBLOCK);
|
||||
}
|
||||
|
||||
void set_block(int fd)
|
||||
{
|
||||
int fl = fcntl(fd, F_GETFL, 0);
|
||||
fcntl(fd, F_SETFL, fl & ~O_NONBLOCK);
|
||||
}
|
||||
|
||||
int fork_and_flush_stdin(int fd, struct buffer *buffer)
|
||||
{
|
||||
int i;
|
||||
if (!buffer_len(buffer))
|
||||
return 0;
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
perror("fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
for (i = 0; i < MAX_FDS; i++)
|
||||
if (i != fd && i != 2)
|
||||
close(i);
|
||||
set_block(fd);
|
||||
write_all(fd, buffer_data(buffer), buffer_len(buffer));
|
||||
exit(0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user