vtest: Refactor vtest_server.c

Refactor the main loop into smaller functions so that it is easier to extend
with more functionality.

There should be no functional change with the exception of some socket
listening code would return error codes as fds, where they now instead call
perrno and exit(1).

Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Jakob Bornecrantz <jakob@collabora.com>
macos/master
Jakob Bornecrantz 6 years ago
parent 21ebb9449b
commit 69d7f802b7
  1. 277
      vtest/vtest_server.c

@ -21,7 +21,6 @@
* OTHER DEALINGS IN THE SOFTWARE. * OTHER DEALINGS IN THE SOFTWARE.
* *
**************************************************************************/ **************************************************************************/
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
#include <stdbool.h> #include <stdbool.h>
@ -39,55 +38,195 @@
#include "vtest_protocol.h" #include "vtest_protocol.h"
static int vtest_open_socket(const char *path)
struct vtest_program
{
const char *socket_name;
int socket;
const char *read_file;
int out_fd;
int in_fd;
bool do_fork;
bool loop;
};
struct vtest_program prog = {
.socket_name = VTEST_DEFAULT_SOCKET_NAME,
.socket = -1,
.read_file = NULL,
.in_fd = -1,
.out_fd = -1,
.do_fork = true,
.loop = true,
};
static void vtest_main_parse_args(int argc, char **argv);
static void vtest_main_set_signal(void);
static void vtest_main_open_read_file(void);
static void vtest_main_open_socket(void);
static void vtest_main_run_renderer(int in_fd, int out_fd);
static void vtest_main_wait_for_socket_accept(void);
static void vtest_main_tidy_fds(void);
static void vtest_main_close_socket(void);
int main(int argc, char **argv)
{
#ifdef __AFL_LOOP
while (__AFL_LOOP(1000)) {
#endif
vtest_main_parse_args(argc, argv);
if (prog.read_file != NULL) {
vtest_main_open_read_file();
goto start;
}
if (prog.do_fork) {
vtest_main_set_signal();
}
vtest_main_open_socket();
restart:
vtest_main_wait_for_socket_accept();
start:
if (prog.do_fork) {
/* fork a renderer process */
if (fork() == 0) {
vtest_main_run_renderer(prog.in_fd, prog.out_fd);
exit(0);
}
} else {
vtest_main_run_renderer(prog.in_fd, prog.out_fd);
}
vtest_main_tidy_fds();
if (prog.loop) {
goto restart;
}
vtest_main_close_socket();
#ifdef __AFL_LOOP
}
#endif
}
static void vtest_main_parse_args(int argc, char **argv)
{
if (argc > 1) {
if (!strcmp(argv[1], "--no-loop-or-fork")) {
prog.do_fork = false;
prog.loop = false;
} else if (!strcmp(argv[1], "--no-fork")) {
prog.do_fork = false;
} else {
prog.read_file = argv[1];
prog.loop = false;
prog.do_fork = false;
}
}
}
static void vtest_main_set_signal(void)
{
struct sigaction sa;
int ret;
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
ret = sigaction(SIGCHLD, &sa, 0);
if (ret == -1) {
perror(NULL);
exit(1);
}
}
static void vtest_main_open_read_file(void)
{
int ret;
ret = open(prog.read_file, O_RDONLY);
if (ret == -1) {
perror(NULL);
exit(1);
}
prog.in_fd = ret;
ret = open("/dev/null", O_WRONLY);
if (ret == -1) {
perror(NULL);
exit(1);
}
prog.out_fd = ret;
}
static void vtest_main_open_socket(void)
{ {
struct sockaddr_un un; struct sockaddr_un un;
int sock;
sock = socket(PF_UNIX, SOCK_STREAM, 0); prog.socket = socket(PF_UNIX, SOCK_STREAM, 0);
if (sock < 0) { if (prog.socket < 0) {
return -1; goto err;
} }
memset(&un, 0, sizeof(un)); memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX; un.sun_family = AF_UNIX;
snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); snprintf(un.sun_path, sizeof(un.sun_path), "%s", prog.socket_name);
unlink(un.sun_path); unlink(un.sun_path);
if (bind(sock, (struct sockaddr *)&un, sizeof(un)) < 0) { if (bind(prog.socket, (struct sockaddr *)&un, sizeof(un)) < 0) {
goto err; goto err;
} }
if (listen(sock, 1) < 0){ if (listen(prog.socket, 1) < 0){
goto err; goto err;
} }
return sock; return;
err: err:
close(sock); perror("Failed to setup socket.");
return -1; exit(1);
} }
static int wait_for_socket_accept(int sock) static void vtest_main_wait_for_socket_accept(void)
{ {
fd_set read_fds; fd_set read_fds;
int new_fd; int new_fd;
int ret; int ret;
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
FD_SET(sock, &read_fds); FD_SET(prog.socket, &read_fds);
ret = select(sock + 1, &read_fds, NULL, NULL, NULL); ret = select(prog.socket + 1, &read_fds, NULL, NULL, NULL);
if (ret < 0) { if (ret < 0) {
return ret; perror("Failed to select on socket!");
exit(1);
}
if (!FD_ISSET(prog.socket, &read_fds)) {
perror("Odd state in fd_set.");
exit(1);
} }
if (FD_ISSET(sock, &read_fds)) { new_fd = accept(prog.socket, NULL, NULL);
new_fd = accept(sock, NULL, NULL); if (new_fd < 0) {
return new_fd; perror("Failed to accept socket.");
exit(1);
} }
return -1;
prog.in_fd = new_fd;
prog.out_fd = new_fd;
} }
typedef int (*vtest_cmd_fptr_t)(uint32_t); typedef int (*vtest_cmd_fptr_t)(uint32_t);
@ -110,7 +249,7 @@ static const vtest_cmd_fptr_t vtest_commands[] = {
vtest_transfer_put2, vtest_transfer_put2,
}; };
static int run_renderer(int in_fd, int out_fd) static void vtest_main_run_renderer(int in_fd, int out_fd)
{ {
int err, ret; int err, ret;
uint32_t header[VTEST_HDR_SIZE]; uint32_t header[VTEST_HDR_SIZE];
@ -164,94 +303,30 @@ static int run_renderer(int in_fd, int out_fd)
fprintf(stderr, "socket failed (%d) - closing renderer\n", err); fprintf(stderr, "socket failed (%d) - closing renderer\n", err);
vtest_destroy_renderer(); vtest_destroy_renderer();
close(in_fd);
return 0;
} }
int main(int argc, char **argv) static void vtest_main_tidy_fds(void)
{ {
int ret, sock = -1, in_fd, out_fd; // out_fd will be closed by the in_fd clause if they are the same.
pid_t pid; if (prog.out_fd == prog.in_fd) {
bool do_fork = true, loop = true; prog.out_fd = -1;
struct sigaction sa;
char *socket_name = VTEST_DEFAULT_SOCKET_NAME;
#ifdef __AFL_LOOP
while (__AFL_LOOP(1000)) {
#endif
if (argc > 1) {
if (!strcmp(argv[1], "--no-loop-or-fork")) {
do_fork = false;
loop = false;
} else if (!strcmp(argv[1], "--no-fork")) {
do_fork = false;
} else {
ret = open(argv[1], O_RDONLY);
if (ret == -1) {
perror(0);
exit(1);
}
in_fd = ret;
ret = open("/dev/null", O_WRONLY);
if (ret == -1) {
perror(0);
exit(1);
}
out_fd = ret;
loop = false;
do_fork = false;
goto start;
}
} }
if (do_fork) { if (prog.in_fd != -1) {
sa.sa_handler = SIG_IGN; close(prog.in_fd);
sigemptyset(&sa.sa_mask); prog.in_fd = -1;
sa.sa_flags = 0;
if (sigaction(SIGCHLD, &sa, 0) == -1) {
perror(0);
exit(1);
}
} }
sock = vtest_open_socket(socket_name); if (prog.out_fd != -1) {
restart: close(prog.out_fd);
in_fd = wait_for_socket_accept(sock); prog.out_fd = -1;
out_fd = in_fd;
start:
if (do_fork) {
/* fork a renderer process */
switch ((pid = fork())) {
case 0:
run_renderer(in_fd, out_fd);
exit(0);
break;
case -1:
default:
close(in_fd);
if (loop) {
goto restart;
}
}
} else {
run_renderer(in_fd, out_fd);
vtest_destroy_renderer();
if (loop) {
goto restart;
}
} }
}
if (sock != -1) { static void vtest_main_close_socket(void)
close(sock); {
} if (prog.socket != -1) {
if (in_fd != out_fd) { close(prog.socket);
close(out_fd); prog.socket = -1;
} }
#ifdef __AFL_LOOP
}
#endif
} }

Loading…
Cancel
Save