GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_processes.cpp
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 195 243 80.2%
Functions: 53 61 86.9%
Branches: 52 164 31.7%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28 #include "gate/processes.hpp"
29 #include "gate/utilities.hpp"
30 #include "gate/times.hpp"
31
32 namespace gate
33 {
34 2 Process::Instance::Instance(id_t processId)
35 2 : procId(processId)
36 {
37 2 }
38 1 Process::Instance::Instance(Instance const& src)
39 1 : procId(src.procId)
40 {
41 1 }
42 1 Process::Instance& Process::Instance::operator=(Instance const& src)
43 {
44 1 this->procId = src.procId;
45 1 return *this;
46 }
47 3 Process::Instance::~Instance()
48 {
49 3 }
50
51 2 Process::id_t Process::Instance::getId() const noexcept
52 {
53 2 return this->procId;
54 }
55 bool_t Process::Instance::wait(uint32_t timeoutMS)
56 {
57 return Process::wait(this->procId, timeoutMS);
58 }
59 void Process::Instance::wait()
60 {
61 Process::wait(this->procId, GATE_PROCESS_ID_INVALID);
62 }
63 1 void Process::Instance::terminate(bool_t systemRequest)
64 {
65 1 Process::terminate(this->procId, systemRequest);
66 1 }
67 1 void Process::Instance::kill()
68 {
69 1 Process::kill(this->procId);
70 1 }
71 1 void Process::Instance::suspend()
72 {
73 1 Process::suspend(this->procId);
74 1 }
75 1 void Process::Instance::resume()
76 {
77 1 Process::resume(this->procId);
78 1 }
79
80
81 1 Process::Child::Child() noexcept
82 : Instance(GATE_PROCESS_ID_INVALID),
83 childHandle(GATE_PROCESS_HANDLE_INVALID),
84 1 childStream(NullStream())
85 {
86 1 }
87 1 Process::Child::~Child() noexcept
88 {
89
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (this->childHandle != GATE_PROCESS_HANDLE_INVALID)
90 {
91 1 Process::close(this->childHandle);
92 }
93 1 }
94
95 1 Process::handle_t Process::Child::getHandle() const noexcept
96 {
97 1 return this->childHandle;
98 }
99
100 1 Stream& Process::Child::getStream() noexcept
101 {
102 1 return this->childStream;
103 }
104
105 1 bool_t Process::Child::wait(uint32_t timeoutMS)
106 {
107 1 return Process::wait(this->childHandle, timeoutMS);
108 }
109 1 void Process::Child::wait()
110 {
111 1 this->wait(GATE_PROCESS_WAIT_INFINITE);
112 1 }
113 void Process::Child::terminate(bool_t systemRequest)
114 {
115 Process::terminate(this->childHandle, systemRequest);
116 }
117 1 void Process::Child::kill()
118 {
119 1 Process::kill(this->childHandle);
120 1 }
121 1 void Process::Child::suspend()
122 {
123 1 Process::suspend(this->childHandle);
124 1 }
125 1 void Process::Child::resume()
126 {
127 1 Process::resume(this->childHandle);
128 1 }
129 1 int Process::Child::getExitCode()
130 {
131 1 return Process::getExitCode(this->childHandle);
132 }
133
134
135 26 void Process::Info::init(gate_process_t const& process)
136 {
137 26 this->name = String(process.name);
138 26 this->path = String(process.path);
139 26 this->owner = String(process.owner);
140
141 26 Mem::copy(&this->impl, &process, sizeof(this->impl));
142 26 this->impl.name = this->name.c_str();
143 26 this->impl.path = this->path.c_str();
144 26 this->impl.owner = this->owner.c_str();
145 26 }
146
147 1 Process::Info::Info()
148 {
149 gate_process_t p;
150 1 Mem::clear(p);
151
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 this->init(p);
152 1 }
153 8 Process::Info::Info(gate_process_t const& proc)
154 8 : impl(proc)
155 {
156
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 this->init(proc);
157 8 }
158 15 Process::Info::Info(Info const& src)
159 15 : impl(src.impl)
160 {
161
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 this->init(src.impl);
162 15 }
163 2 Process::Info& Process::Info::operator=(Info const& src)
164 {
165
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (this != &src)
166 {
167 2 this->init(src.impl);
168 }
169 2 return *this;
170 }
171
172 1 Process::id_t Process::Info::Id() const
173 {
174 1 return this->impl.pid;
175 }
176 1 Process::id_t Process::Info::Parent() const
177 {
178 1 return this->impl.parent_pid;
179 }
180 1 uint64_t Process::Info::MemoryUsed() const
181 {
182 1 return this->impl.memory_used;
183 }
184 1 time::Milliseconds Process::Info::UpTime() const
185 {
186 1 return time::Milliseconds(static_cast<time::duration_value_t>(this->impl.uptime));
187 }
188 1 time::Milliseconds Process::Info::CpuTime() const
189 {
190 1 return time::Milliseconds(static_cast<time::duration_value_t>(this->impl.cputime));
191 }
192 1 uint64_t Process::Info::Resources() const
193 {
194 1 return this->impl.resources;
195 }
196 1 String Process::Info::Name() const
197 {
198 1 return this->name;
199 }
200 1 String Process::Info::Path() const
201 {
202 1 return this->path;
203 }
204 1 String Process::Info::Owner() const
205 {
206 1 return this->owner;
207 }
208
209 static gate_bool_t Process_list_callback(gate_process_t* process, void* userparam)
210 {
211 Process::ListCallback* cb = static_cast<Process::ListCallback*>(userparam);
212 Process::Info info(*process);
213 gate_bool_t ret = true;
214 cb->invoke(info, ret);
215 return ret;
216 }
217
218 1 Process::id_t Process::getId()
219 {
220 1 gate_process_id_t id = 0;
221
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_process_get_id(&id);
222
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_ERROR(result);
223 1 return id;
224 }
225
226
227 void Process::list(ListCallback callback, enumint_t flags)
228 {
229 result_t result = gate_process_enum(&Process_list_callback, &callback, flags);
230 GATEXX_CHECK_EXCEPTION(result);
231 }
232
233 7 static gate_bool_t Process_list_array_callback(gate_process_t* process, void* userparam)
234 {
235 7 ArrayList<Process::Info>* ptrList = static_cast<ArrayList< Process::Info>*>(userparam);
236
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 Process::Info info(*process);
237 try
238 {
239
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 ptrList->add(info);
240 }
241 catch (...) {}
242 14 return true;
243 }
244
245 1 Array<Process::Info> Process::list()
246 {
247 static enumint_t const flagsListAll = ListFlag_All;
248 1 return Process::list(flagsListAll);
249 }
250
251 1 Array<Process::Info> Process::list(enumint_t flags)
252 {
253
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 ArrayList<Process::Info> list;
254
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_process_enum(&Process_list_array_callback, &list, flags);
255
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
256
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return list.toArray();
257 }
258
259 1 Process::Info Process::getInfo(id_t pid, enumint_t flags)
260 {
261 gate_process_infobuffer_t buffer;
262
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_process_getinfo(&buffer, pid, flags);
263
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
264
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return Info(buffer.process);
265 }
266
267 2 void Process::start(String const& executablepath, Array<String> const& args,
268 String const& workdir, Array<String> const& envvars, enumint_t flags,
269 handle_t* result_handle,
270 id_t* result_pid,
271 Stream* result_stream)
272 {
273 gate_string_t arglist[128];
274 gate_string_t envlist[128];
275 2 gate_process_stream_t* streamptr = NULL;
276
277
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 size_t argcount = util::convertStringArray(args, arglist, 128);
278
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 size_t envcount = util::convertStringArray(envvars, envlist, 128);
279
280
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 result_t result = gate_process_start(executablepath.c_impl(), arglist, argcount, workdir.c_impl(),
281 envlist, envcount, flags, result_handle, result_pid,
282 result_stream ? &streamptr : NULL);
283
284
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 util::releaseStringArray(envlist, envcount);
285
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 util::releaseStringArray(arglist, argcount);
286
287
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2 GATEXX_CHECK_EXCEPTION(result);
288
289
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (streamptr)
290 {
291
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (result_stream)
292 {
293
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 *result_stream = Stream((gate_stream_t*)streamptr);
294 }
295 else
296 {
297 gate_object_release(streamptr);
298 }
299 }
300 2 }
301
302 1 void Process::start(String const& executablepath, Array<String> const& args,
303 String const& workdir, Array<String> const& envvars, enumint_t flags,
304 Child& child)
305 {
306 1 handle_t handle = GATE_PROCESS_HANDLE_INVALID;
307 1 id_t id = GATE_PROCESS_ID_INVALID;
308 2 Stream strm = NullStream();
309
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 Process::start(executablepath, args, workdir, envvars, flags, &handle, &id, &strm);
310 1 child.childHandle = handle;
311 1 child.procId = id;
312 1 child.childStream = strm;
313 1 }
314
315
316 void Process::start(String const& executablepath, Array<String> const& args,
317 String const& workdir, Array<String> const& envvars, enumint_t flags,
318 String const& sessionlocation,
319 String const& username, String const& password,
320 handle_t* result_handle,
321 id_t* result_pid,
322 Stream* result_stream)
323 {
324 gate_string_t arglist[128];
325 gate_string_t envlist[128];
326 char session[256];
327 char user[256];
328 char pass[512];
329 gate_process_stream_t* streamptr = NULL;
330
331 sessionlocation.copyTo(session, sizeof(session));
332 username.copyTo(user, sizeof(user));
333 password.copyTo(pass, sizeof(pass));
334
335 size_t argcount = util::convertStringArray(args, arglist, 128);
336 size_t envcount = util::convertStringArray(envvars, envlist, 128);
337
338 result_t result = gate_process_start_ex(executablepath.c_impl(), arglist, argcount, workdir.c_impl(),
339 envlist, envcount, flags,
340 session, user, pass,
341 result_handle, result_pid,
342 result_stream ? &streamptr : NULL);
343
344 util::releaseStringArray(envlist, envcount);
345 util::releaseStringArray(arglist, argcount);
346
347 GATEXX_CHECK_EXCEPTION(result);
348
349 if (streamptr)
350 {
351 if (result_stream)
352 {
353 *result_stream = Stream((gate_stream_t*)streamptr);
354 }
355 else
356 {
357 gate_object_release(streamptr);
358 }
359 }
360 }
361
362 1 VoidResult Process::close(handle_t& handle)
363 {
364
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_process_close(&handle);
365
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return makeResult(result);
366 }
367
368 1 int Process::getExitCode(handle_t& handle)
369 {
370 1 int exitcode = 0;
371
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_process_get_exitcode(&handle, &exitcode);
372
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
373 1 return exitcode;
374 }
375
376 1 void Process::run(String const& executablepath, Array<String> const& args,
377 String const& workdir, Array<String> const& envVars,
378 enumint_t flags, Stream* output, int* exit_code)
379 {
380 gate_string_t argslist[128];
381 gate_string_t envlist[128];
382
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 gate_stream_t* ptr_stream = ((output != NULL) ? output->c_impl() : NULL);
383
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 size_t argscount = util::convertStringArray(args, argslist, 128);
384
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 size_t envcount = util::convertStringArray(envVars, envlist, 128);
385
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 result_t result = gate_process_run(executablepath.c_impl(), argslist, argscount, workdir.c_impl(),
386 envlist, envcount, flags,
387 output ? ptr_stream : NULL,
388 exit_code);
389
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 util::releaseStringArray(envlist, envcount);
390
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 util::releaseStringArray(argslist, argscount);
391
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
392 1 }
393
394 1 bool_t Process::wait(handle_t& handle, uint32_t timeoutms)
395 {
396 1 result_t result = gate_process_wait(&handle, timeoutms);
397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (results::Timeout == result)
398 {
399 return false;
400 }
401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
402 1 return true;
403 }
404
405 bool_t Process::wait(id_t pid, uint32_t timeoutms)
406 {
407 result_t result = gate_process_wait_pid(pid, timeoutms);
408 if (results::Timeout == result)
409 {
410 return false;
411 }
412 GATEXX_CHECK_EXCEPTION(result);
413 return true;
414 }
415
416 void Process::terminate(handle_t& handle, bool_t system_request)
417 {
418 result_t result = gate_process_terminate(&handle, system_request);
419 GATEXX_CHECK_EXCEPTION(result);
420 }
421
422 1 void Process::terminate(id_t pid, bool_t system_request)
423 {
424 1 result_t result = gate_process_terminate_pid(pid, system_request);
425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
426 1 }
427
428 1 void Process::kill(handle_t& handle)
429 {
430 1 result_t result = gate_process_kill(&handle);
431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
432 1 }
433
434 1 void Process::kill(id_t pid)
435 {
436 1 result_t result = gate_process_kill_pid(pid);
437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
438 1 }
439
440 1 void Process::suspend(handle_t& handle)
441 {
442 1 result_t result = gate_process_suspend(&handle);
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
444 1 }
445
446 1 void Process::suspend(id_t pid)
447 {
448 1 result_t result = gate_process_suspend_pid(pid);
449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
450 1 }
451
452 1 void Process::resume(handle_t& handle)
453 {
454 1 result_t result = gate_process_resume(&handle);
455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
456 1 }
457
458 1 void Process::resume(id_t pid)
459 {
460 1 result_t result = gate_process_resume_pid(pid);
461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
462 1 }
463
464 1 String Process::printPid(gate_process_id_t pid)
465 {
466 char buffer[64];
467
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 size_t used = gate_process_print_pid(pid, buffer, 64);
468
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return String(buffer, used);
469 }
470
471 1 Process::id_t Process::parsePid(String const& text)
472 {
473 1 id_t ret = 0;
474
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 size_t len = gate_process_parse_pid(text.c_str(), text.length(), &ret);
475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len == 0)
476 {
477 GATEXX_RAISE_EXCEPTION(results::InvalidData, "Cannot parse PID", 0);
478 }
479 1 return ret;
480 }
481
482 } // end of namespace gate
483