GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_processes.cpp
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 160 245 65.3%
Functions: 42 60 70.0%
Branches: 48 170 28.2%

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 Process::Instance::Instance(Instance const& src)
39 : procId(src.procId)
40 {
41 }
42 Process::Instance& Process::Instance::operator=(Instance const& src)
43 {
44 this->procId = src.procId;
45 return *this;
46 }
47 2 Process::Instance::~Instance()
48 {
49 2 }
50
51 1 Process::id_t Process::Instance::getId() const noexcept
52 {
53 1 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 void Process::Instance::terminate(bool_t systemRequest)
64 {
65 Process::terminate(this->procId, systemRequest);
66 }
67 void Process::Instance::kill()
68 {
69 Process::kill(this->procId);
70 }
71 void Process::Instance::suspend()
72 {
73 Process::suspend(this->procId);
74 }
75 void Process::Instance::resume()
76 {
77 Process::resume(this->procId);
78 }
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(enumint_t flags)
246 {
247
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 ArrayList<Process::Info> list;
248
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_process_enum(&Process_list_array_callback, &list, flags);
249
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
250
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return list.toArray();
251 }
252
253 1 Process::Info Process::getInfo(id_t pid, enumint_t flags)
254 {
255 gate_process_infobuffer_t buffer;
256
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_process_getinfo(&buffer, pid, flags);
257
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
258
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return Info(buffer.process);
259 }
260
261 1 void Process::start(String const& executablepath, Array<String> const& args,
262 String const& workdir, Array<String> const& envvars, enumint_t flags,
263 handle_t* result_handle,
264 id_t* result_pid,
265 Stream* result_stream)
266 {
267 gate_string_t arglist[128];
268 gate_string_t envlist[128];
269 1 gate_process_stream_t* streamptr = NULL;
270
271
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 size_t argcount = util::convertStringArray(args, arglist, 128);
272
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 size_t envcount = util::convertStringArray(envvars, envlist, 128);
273
274
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_start(executablepath.c_impl(), arglist, argcount, workdir.c_impl(),
275 envlist, envcount, flags, result_handle, result_pid,
276 result_stream ? &streamptr : NULL);
277
278
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 util::releaseStringArray(envlist, envcount);
279
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 util::releaseStringArray(arglist, argcount);
280
281
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
282
283
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (streamptr)
284 {
285
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (result_stream)
286 {
287
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 *result_stream = Stream((gate_stream_t*)streamptr);
288 }
289 else
290 {
291 gate_object_release(streamptr);
292 }
293 }
294 1 }
295
296 1 void Process::start(String const& executablepath, Array<String> const& args,
297 String const& workdir, Array<String> const& envvars, enumint_t flags,
298 Child& child)
299 {
300 1 handle_t handle = GATE_PROCESS_HANDLE_INVALID;
301 1 id_t id = GATE_PROCESS_ID_INVALID;
302 2 Stream strm = NullStream();
303
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 Process::start(executablepath, args, workdir, envvars, flags, &handle, &id, &strm);
304 1 child.childHandle = handle;
305 1 child.procId = id;
306 1 child.childStream = strm;
307 1 }
308
309
310 void Process::start(String const& executablepath, Array<String> const& args,
311 String const& workdir, Array<String> const& envvars, enumint_t flags,
312 String const& sessionlocation,
313 String const& username, String const& password,
314 handle_t* result_handle,
315 id_t* result_pid,
316 Stream* result_stream)
317 {
318 gate_string_t arglist[128];
319 gate_string_t envlist[128];
320 char session[256];
321 char user[256];
322 char pass[512];
323 gate_process_stream_t* streamptr = NULL;
324
325 sessionlocation.copyTo(session, sizeof(session));
326 username.copyTo(user, sizeof(user));
327 password.copyTo(pass, sizeof(pass));
328
329 size_t argcount = util::convertStringArray(args, arglist, 128);
330 size_t envcount = util::convertStringArray(envvars, envlist, 128);
331
332 result_t result = gate_process_start_ex(executablepath.c_impl(), arglist, argcount, workdir.c_impl(),
333 envlist, envcount, flags,
334 session, user, pass,
335 result_handle, result_pid,
336 result_stream ? &streamptr : NULL);
337
338 util::releaseStringArray(envlist, envcount);
339 util::releaseStringArray(arglist, argcount);
340
341 GATEXX_CHECK_EXCEPTION(result);
342
343 if (streamptr)
344 {
345 if (result_stream)
346 {
347 *result_stream = Stream((gate_stream_t*)streamptr);
348 }
349 else
350 {
351 gate_object_release(streamptr);
352 }
353 }
354 }
355
356 1 VoidResult Process::close(handle_t& handle)
357 {
358
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_process_close(&handle);
359
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return makeResult(result);
360 }
361
362 1 int Process::getExitCode(handle_t& handle)
363 {
364 1 int exitcode = 0;
365
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_process_get_exitcode(&handle, &exitcode);
366
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
367 1 return exitcode;
368 }
369
370 1 void Process::run(String const& executablepath, Array<String> const& args,
371 String const& workdir, Array<String> const& envVars,
372 enumint_t flags, Stream* output, int* exit_code)
373 {
374 gate_string_t argslist[128];
375 gate_string_t envlist[128];
376 1 gate_stream_t* ptr_stream = NULL;
377
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 size_t argscount = util::convertStringArray(args, argslist, 128);
378
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 size_t envcount = util::convertStringArray(envVars, envlist, 128);
379
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(),
380 envlist, envcount, flags,
381 output ? ptr_stream : NULL, exit_code);
382
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 util::releaseStringArray(envlist, envcount);
383
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 util::releaseStringArray(argslist, argscount);
384
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptr_stream)
386 {
387 if (output)
388 {
389 *output = Stream(ptr_stream);
390 }
391 else
392 {
393 gate_object_release(ptr_stream);
394 }
395 }
396 1 }
397
398 1 bool_t Process::wait(handle_t& handle, uint32_t timeoutms)
399 {
400 1 result_t result = gate_process_wait(&handle, timeoutms);
401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (results::Timeout == result)
402 {
403 return false;
404 }
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
406 1 return true;
407 }
408
409 bool_t Process::wait(id_t pid, uint32_t timeoutms)
410 {
411 result_t result = gate_process_wait_pid(pid, timeoutms);
412 if (results::Timeout == result)
413 {
414 return false;
415 }
416 GATEXX_CHECK_EXCEPTION(result);
417 return true;
418 }
419
420 void Process::terminate(handle_t& handle, bool_t system_request)
421 {
422 result_t result = gate_process_terminate(&handle, system_request);
423 GATEXX_CHECK_EXCEPTION(result);
424 }
425
426 void Process::terminate(id_t pid, bool_t system_request)
427 {
428 result_t result = gate_process_terminate_pid(pid, system_request);
429 GATEXX_CHECK_EXCEPTION(result);
430 }
431
432 1 void Process::kill(handle_t& handle)
433 {
434 1 result_t result = gate_process_kill(&handle);
435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
436 1 }
437
438 void Process::kill(id_t pid)
439 {
440 result_t result = gate_process_kill_pid(pid);
441 GATEXX_CHECK_EXCEPTION(result);
442 }
443
444 1 void Process::suspend(handle_t& handle)
445 {
446 1 result_t result = gate_process_suspend(&handle);
447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
448 1 }
449
450 void Process::suspend(id_t pid)
451 {
452 result_t result = gate_process_suspend_pid(pid);
453 GATEXX_CHECK_EXCEPTION(result);
454 }
455
456 1 void Process::resume(handle_t& handle)
457 {
458 1 result_t result = gate_process_resume(&handle);
459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
460 1 }
461
462 void Process::resume(id_t pid)
463 {
464 result_t result = gate_process_resume_pid(pid);
465 GATEXX_CHECK_EXCEPTION(result);
466 }
467
468 1 String Process::printPid(gate_process_id_t pid)
469 {
470 char buffer[64];
471
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 size_t used = gate_process_print_pid(pid, buffer, 64);
472
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return String(buffer, used);
473 }
474
475 1 Process::id_t Process::parsePid(String const& text)
476 {
477 1 id_t ret = 0;
478
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);
479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len == 0)
480 {
481 GATEXX_RAISE_EXCEPTION(results::InvalidData, "Cannot parse PID", 0);
482 }
483 1 return ret;
484 }
485
486
487 } // end of namespace gate
488