GCC Code Coverage Report


Directory: src/
File: src/worker.c
Date: 2024-04-25 03:45:42
Exec Total Coverage
Lines: 106 151 70.2%
Branches: 27 62 43.5%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 * This file is part of the "cimple" project.
4 * For details, see https://github.com/egor-tensin/cimple.
5 * Distributed under the MIT License.
6 */
7
8 #include "worker.h"
9 #include "ci.h"
10 #include "command.h"
11 #include "compiler.h"
12 #include "const.h"
13 #include "event_loop.h"
14 #include "git.h"
15 #include "log.h"
16 #include "net.h"
17 #include "process.h"
18 #include "protocol.h"
19 #include "run_queue.h"
20 #include "signal.h"
21
22 #include <poll.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 struct worker {
27 struct settings *settings;
28
29 int stopping;
30
31 struct cmd_dispatcher *cmd_dispatcher;
32
33 struct event_loop *event_loop;
34 int signalfd;
35
36 struct run *run;
37 };
38
39 54 static struct settings *worker_settings_copy(const struct settings *src)
40 {
41 54 struct settings *result = malloc(sizeof(*src));
42
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (!result) {
43 log_errno("malloc");
44 return NULL;
45 }
46
47 54 result->host = strdup(src->host);
48
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (!result->host) {
49 log_errno("strdup");
50 goto free_result;
51 }
52
53 54 result->port = strdup(src->port);
54
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (!result->port) {
55 log_errno("strdup");
56 goto free_host;
57 }
58
59 54 return result;
60
61 free_host:
62 free((void *)result->host);
63
64 free_result:
65 free(result);
66
67 return NULL;
68 }
69
70 54 static void worker_settings_destroy(struct settings *settings)
71 {
72 54 free((void *)settings->port);
73 54 free((void *)settings->host);
74 54 free(settings);
75 54 }
76
77 54 static int worker_set_stopping(UNUSED struct event_loop *loop, UNUSED int fd, UNUSED short revents,
78 void *_worker)
79 {
80 54 struct worker *worker = (struct worker *)_worker;
81 54 worker->stopping = 1;
82 54 return 0;
83 }
84
85 9180 static int worker_handle_cmd_start_run(const struct jsonrpc_request *request,
86 UNUSED struct jsonrpc_response **response, void *_ctx)
87 {
88 9180 struct cmd_conn_ctx *ctx = (struct cmd_conn_ctx *)_ctx;
89 9180 struct worker *worker = (struct worker *)ctx->arg;
90 9180 int ret = 0;
91
92 9180 ret = request_parse_start_run(request, &worker->run);
93
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
94 return ret;
95
96 9180 return ret;
97 }
98
99 static struct cmd_desc commands[] = {
100 {CMD_START_RUN, worker_handle_cmd_start_run},
101 };
102
103 static const size_t numof_commands = sizeof(commands) / sizeof(commands[0]);
104
105 54 int worker_create(struct worker **_worker, const struct settings *settings)
106 {
107 54 int ret = 0;
108
109 54 struct worker *worker = malloc(sizeof(struct worker));
110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (!worker) {
111 log_errno("malloc");
112 return -1;
113 }
114
115 54 worker->settings = worker_settings_copy(settings);
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (!worker->settings) {
117 ret = -1;
118 goto free;
119 }
120
121 54 worker->stopping = 0;
122
123 54 ret = cmd_dispatcher_create(&worker->cmd_dispatcher, commands, numof_commands, worker);
124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (ret < 0)
125 goto free_settings;
126
127 54 ret = event_loop_create(&worker->event_loop);
128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (ret < 0)
129 goto destroy_cmd_dispatcher;
130
131 54 ret = signalfd_create_sigterms();
132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (ret < 0)
133 goto destroy_event_loop;
134 54 worker->signalfd = ret;
135
136 54 ret = event_loop_add(worker->event_loop, worker->signalfd, POLLIN, worker_set_stopping,
137 worker);
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (ret < 0)
139 goto close_signalfd;
140
141 54 ret = libgit_init();
142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (ret < 0)
143 goto close_signalfd;
144
145 54 *_worker = worker;
146 54 return ret;
147
148 close_signalfd:
149 signalfd_destroy(worker->signalfd);
150
151 destroy_event_loop:
152 event_loop_destroy(worker->event_loop);
153
154 destroy_cmd_dispatcher:
155 cmd_dispatcher_destroy(worker->cmd_dispatcher);
156
157 free_settings:
158 worker_settings_destroy(worker->settings);
159
160 free:
161 free(worker);
162
163 return ret;
164 }
165
166 54 void worker_destroy(struct worker *worker)
167 {
168
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
54 log("Shutting down\n");
169
170 54 libgit_shutdown();
171 54 signalfd_destroy(worker->signalfd);
172 54 event_loop_destroy(worker->event_loop);
173 54 cmd_dispatcher_destroy(worker->cmd_dispatcher);
174 54 worker_settings_destroy(worker->settings);
175 54 free(worker);
176 54 }
177
178 9180 static int worker_do_run(struct worker *worker)
179 {
180 9180 int ret = 0;
181
182 9180 struct proc_output *result = NULL;
183 9180 ret = proc_output_create(&result);
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
185 return ret;
186
187 9180 ret = ci_run_git_repo(run_get_repo_url(worker->run), run_get_repo_rev(worker->run), result);
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0) {
189 log_err("Run failed with an error\n");
190 goto free_output;
191 }
192
193 9180 proc_output_dump(result);
194
195 9180 struct jsonrpc_request *finished_request = NULL;
196
197 9180 ret = request_create_finished_run(&finished_request, run_get_id(worker->run), result);
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
199 goto free_output;
200
201 9180 ret = net_connect(worker->settings->host, worker->settings->port);
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
203 goto free_request;
204 9180 int fd = ret;
205
206 9180 ret = jsonrpc_request_send(finished_request, fd);
207
1/2
✓ Branch 0 taken 9180 times.
✗ Branch 1 not taken.
9180 if (ret < 0)
208 goto close_conn;
209
210 9180 close_conn:
211 9180 net_close(fd);
212
213 9180 free_request:
214 9180 jsonrpc_request_destroy(finished_request);
215
216 9180 free_output:
217 9180 proc_output_destroy(result);
218
219 9180 run_destroy(worker->run);
220
221 9180 return ret;
222 }
223
224 9234 static int worker_get_run(struct worker *worker)
225 {
226 9234 int ret = 0, fd = -1;
227
228 9234 ret = net_connect(worker->settings->host, worker->settings->port);
229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9234 times.
9234 if (ret < 0)
230 return ret;
231 9234 fd = ret;
232
233 9234 struct jsonrpc_request *new_worker_request = NULL;
234 9234 ret = request_create_new_worker(&new_worker_request);
235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9234 times.
9234 if (ret < 0)
236 goto close;
237
238 9234 ret = jsonrpc_request_send(new_worker_request, fd);
239 9234 jsonrpc_request_destroy(new_worker_request);
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9234 times.
9234 if (ret < 0)
241 goto close;
242
243 9234 ret = event_loop_add_once(worker->event_loop, fd, POLLIN, cmd_dispatcher_handle_event,
244 9234 worker->cmd_dispatcher);
245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9234 times.
9234 if (ret < 0)
246 goto close;
247
248
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9234 times.
9234 log("Waiting for a new command\n");
249
250 9234 ret = event_loop_run(worker->event_loop);
251
1/2
✓ Branch 0 taken 9234 times.
✗ Branch 1 not taken.
9234 if (ret < 0)
252 goto close;
253
254 9234 close:
255 9234 net_close(fd);
256
257 9234 return ret;
258 }
259
260 54 int worker_main(struct worker *worker)
261 {
262 54 int ret = 0;
263
264 while (1) {
265 9234 ret = worker_get_run(worker);
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9234 times.
9234 if (ret < 0)
267 return ret;
268
269
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 9180 times.
9234 if (worker->stopping)
270 54 break;
271
272 9180 ret = worker_do_run(worker);
273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
274 return ret;
275 }
276
277 54 return ret;
278 }
279