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:
Rafal Wojtczuk 2011-03-17 18:15:04 +01:00
parent 53b517f6a5
commit 1d24ef9d1a
5 changed files with 43 additions and 5 deletions

View File

@ -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:

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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);
}