Added a function to wait on any process completing

Added function to check if all processes are finished without blocking
Added a function to set a uniproc_process object to a known invalid value
Added a function to check if a process is a known invalid value
Added userdata variable to struct as well as functions to set/get it

AMEND: Updated uniproc_close_process to set the process to a known invalid value
All functions now ignore uniproc_process's with a known invalid value
uniproc_create_process will now return a known invalid value if it fails to create a process
This commit is contained in:
2025-03-06 15:29:37 +11:00
parent f4927bf136
commit 682773a934
4 changed files with 170 additions and 19 deletions

View File

@@ -21,19 +21,61 @@ uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, c
// Actually create the pipes
if (!CreatePipe(&out, &child_out, &pipe_attribs, 0))
exit(EXIT_FAILURE);
{
uniproc_nullify_processes(p, 1);
return p;
}
if (!CreatePipe(&err, &child_err, &pipe_attribs, 0))
exit(EXIT_FAILURE);
{
CloseHandle(child_out);
CloseHandle(out);
uniproc_nullify_processes(p, 1);
return p;
}
if (!CreatePipe(&child_in, &in, &pipe_attribs, 0))
exit(EXIT_FAILURE);
{
CloseHandle(child_out);
CloseHandle(out);
CloseHandle(child_err);
CloseHandle(err);
uniproc_nullify_processes(p, 1);
return p;
}
// Unset inherrit flags for the pipes
if (!SetHandleInformation(out, HANDLE_FLAG_INHERIT, 0))
exit(EXIT_FAILURE);
{
CloseHandle(child_in);
CloseHandle(in);
CloseHandle(child_out);
CloseHandle(out);
CloseHandle(child_err);
CloseHandle(err);
uniproc_nullify_processes(p, 1);
return p;
}
if (!SetHandleInformation(err, HANDLE_FLAG_INHERIT, 0))
exit(EXIT_FAILURE);
{
CloseHandle(child_in);
CloseHandle(in);
CloseHandle(child_out);
CloseHandle(out);
CloseHandle(child_err);
CloseHandle(err);
uniproc_nullify_processes(p, 1);
return p;
}
if (!SetHandleInformation(in, HANDLE_FLAG_INHERIT, 0))
exit(EXIT_FAILURE);
{
CloseHandle(child_in);
CloseHandle(in);
CloseHandle(child_out);
CloseHandle(out);
CloseHandle(child_err);
CloseHandle(err);
uniproc_nullify_processes(p, 1);
return p;
}
// Create child process
uniproc_process p;
@@ -82,7 +124,16 @@ uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, c
free(p_cmd);
if (!is_ok)
exit(EXIT_FAILURE);
{
CloseHandle(child_in);
CloseHandle(in);
CloseHandle(child_out);
CloseHandle(out);
CloseHandle(child_err);
CloseHandle(err);
uniproc_nullify_processes(p, 1);
return p;
}
p.err = _fdopen(_open_osfhandle((intptr_t)err, _O_RDONLY), "r");
p.out = _fdopen(_open_osfhandle((intptr_t)out, _O_RDONLY), "r");
@@ -118,6 +169,37 @@ void uniproc_close_process(uniproc_process* p)
fclose(p->in);
fclose(p->out);
fclose(p->err);
uniproc_nullify_processes(p, 1);
}
bool uniproc_are_processes_finished(const uniproc_process* p, const size_t num_processes)
{
HANDLE* h = (HANDLE*)malloc(num_processes*sizeof(HANDLE));
DWORD ret = WaitForMultipleObjects(num_processes, h, true, 0);
free(h);
return ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + num_processes;
}
void uniproc_nullify_processes(uniproc_process* p, const size_t num_processes)
{ memset(p, 0, num_processes * sizeof(uniproc_process)); }
void uniproc_is_process_null(const uniproc_process* p)
{ return p->_proc_hdl == NULL; }
void uniproc_await_any_processes(const uniproc_process* p, const size_t num_processes)
{
HANDLE* h = (HANDLE*)malloc(num_processes * sizeof(HANDLE));
WaitForMultipleObjects(num_processes, h, false, INFINITE);
free(h);
}
void uniproc_set_userdata(uniproc_process* p, const uint64_t userdata)
{ p->userdata = userdata; }
void uniproc_set_userdata(uniproc_process * p, void const* userdata)
{ p->userdata = (uint64_t)userdata; }
void* uniproc_get_userdata(uniproc_process* p)
{ return (void*)p->userdata; }
#endif