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
|
all: qrexec_daemon qrexec_agent qrexec_client
|
||||||
qrexec_daemon: qrexec_daemon.o unix_server.o $(COMMONIOALL) txrx-vchan.o buffer.o write_stdin.o
|
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)
|
$(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
|
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 $(XENLIBS)
|
$(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
|
qrexec_client: qrexec_client.o $(COMMONIOALL) exec.o
|
||||||
$(CC) -g -o qrexec_client qrexec_client.o $(COMMONIOALL) exec.o
|
$(CC) -g -o qrexec_client qrexec_client.o $(COMMONIOALL) exec.o
|
||||||
clean:
|
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,
|
int write_stdin(int fd, int clid, char *data, int len,
|
||||||
struct buffer *buffer);
|
struct buffer *buffer);
|
||||||
void set_nonblock(int fd);
|
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;
|
int i;
|
||||||
if (!client_info[clid].pid)
|
if (!client_info[clid].pid)
|
||||||
return;
|
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);
|
kill(client_info[clid].pid, SIGKILL);
|
||||||
|
#endif
|
||||||
if (status != -1)
|
if (status != -1)
|
||||||
send_exit_code(clid, status);
|
send_exit_code(clid, status);
|
||||||
|
|
||||||
|
@ -118,10 +118,15 @@ void handle_new_client()
|
|||||||
max_client_fd = fd;
|
max_client_fd = fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int children_count;
|
||||||
|
|
||||||
void flush_client(int fd)
|
void flush_client(int fd)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct server_header s_hdr;
|
struct server_header s_hdr;
|
||||||
|
|
||||||
|
if (fork_and_flush_stdin(fd, &clients[fd].buffer))
|
||||||
|
children_count++;
|
||||||
close(fd);
|
close(fd);
|
||||||
clients[fd].state = CLIENT_INVALID;
|
clients[fd].state = CLIENT_INVALID;
|
||||||
buffer_free(&clients[fd].buffer);
|
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;
|
int child_exited;
|
||||||
|
|
||||||
void sigchld_handler(int x)
|
void sigchld_handler(int x)
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <ioall.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "qrexec.h"
|
#include "qrexec.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "glue.h"
|
#include "glue.h"
|
||||||
@ -66,7 +68,7 @@ int write_stdin(int fd, int clid, char *data, int len,
|
|||||||
buffer_append(buffer, data, len);
|
buffer_append(buffer, data, len);
|
||||||
return WRITE_STDIN_BUFFERED;
|
return WRITE_STDIN_BUFFERED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = write(fd, data, len);
|
ret = write(fd, data, len);
|
||||||
if (ret == len)
|
if (ret == len)
|
||||||
return WRITE_STDIN_OK;
|
return WRITE_STDIN_OK;
|
||||||
@ -96,3 +98,31 @@ void set_nonblock(int fd)
|
|||||||
int fl = fcntl(fd, F_GETFL, 0);
|
int fl = fcntl(fd, F_GETFL, 0);
|
||||||
fcntl(fd, F_SETFL, fl | O_NONBLOCK);
|
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