xref: /aosp_15_r20/external/virglrenderer/src/proxy/proxy_server.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1 /*
2  * Copyright 2021 Google LLC
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "proxy_server.h"
7 
8 #include <signal.h>
9 #include <sys/wait.h>
10 #include <unistd.h>
11 
12 #include "server/render_protocol.h"
13 
14 int
proxy_server_connect(struct proxy_server * srv)15 proxy_server_connect(struct proxy_server *srv)
16 {
17    int client_fd = srv->client_fd;
18    /* transfer ownership */
19    srv->client_fd = -1;
20    return client_fd;
21 }
22 
23 void
proxy_server_destroy(struct proxy_server * srv)24 proxy_server_destroy(struct proxy_server *srv)
25 {
26    if (srv->pid >= 0) {
27       kill(srv->pid, SIGKILL);
28 
29       siginfo_t siginfo = { 0 };
30       waitid(P_PID, srv->pid, &siginfo, WEXITED);
31    }
32 
33    if (srv->client_fd >= 0)
34       close(srv->client_fd);
35 
36    free(srv);
37 }
38 
39 static bool
proxy_server_fork(struct proxy_server * srv)40 proxy_server_fork(struct proxy_server *srv)
41 {
42    int socket_fds[2];
43    if (!proxy_socket_pair(socket_fds))
44       return false;
45    const int client_fd = socket_fds[0];
46    const int remote_fd = socket_fds[1];
47 
48    pid_t pid = fork();
49    if (pid < 0) {
50       proxy_log("failed to fork proxy server");
51       close(client_fd);
52       close(remote_fd);
53       return false;
54    }
55 
56    if (pid > 0) {
57       srv->pid = pid;
58       srv->client_fd = client_fd;
59       close(remote_fd);
60    } else {
61       close(client_fd);
62 
63       /* do not receive signals from terminal */
64       setpgid(0, 0);
65 
66       char fd_str[16];
67       snprintf(fd_str, sizeof(fd_str), "%d", remote_fd);
68 
69       char *const argv[] = {
70          RENDER_SERVER_EXEC_PATH,
71          "--socket-fd",
72          fd_str,
73          NULL,
74       };
75       execv(argv[0], argv);
76 
77       proxy_log("failed to exec %s: %s", argv[0], strerror(errno));
78       close(remote_fd);
79       exit(-1);
80    }
81 
82    return true;
83 }
84 
85 static bool
proxy_server_init_fd(struct proxy_server * srv)86 proxy_server_init_fd(struct proxy_server *srv)
87 {
88    /* the fd represents a connection to the server */
89    srv->client_fd = proxy_renderer.cbs->get_server_fd(RENDER_SERVER_VERSION);
90    if (srv->client_fd < 0)
91       return false;
92 
93    return true;
94 }
95 
96 struct proxy_server *
proxy_server_create(void)97 proxy_server_create(void)
98 {
99    struct proxy_server *srv = calloc(1, sizeof(*srv));
100    if (!srv)
101       return NULL;
102 
103    srv->pid = -1;
104 
105    if (!proxy_server_init_fd(srv)) {
106       /* start the render server on demand when the client does not provide a
107        * server fd
108        */
109       if (!proxy_server_fork(srv)) {
110          free(srv);
111          return NULL;
112       }
113    }
114 
115    if (!proxy_socket_is_seqpacket(srv->client_fd)) {
116       proxy_log("invalid client fd type");
117       close(srv->client_fd);
118       free(srv);
119       return NULL;
120    }
121 
122    proxy_log("proxy server with pid %d", srv->pid);
123 
124    return srv;
125 }
126