Compare commits
14 Commits
f4927bf136
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
fe9ed46859
|
|||
|
8948e75d06
|
|||
|
c23fd535b0
|
|||
|
f93fe3deae
|
|||
|
e4369a403f
|
|||
|
e92fbe04cb
|
|||
|
0259a5bb25
|
|||
|
6060ea8960
|
|||
|
5c5abfd36c
|
|||
|
f423cd3db2
|
|||
|
500fe17076
|
|||
|
12cc5bd38e
|
|||
|
682773a934
|
|||
|
7c437b8f30
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@
|
|||||||
/test.ilk
|
/test.ilk
|
||||||
/test.pdb
|
/test.pdb
|
||||||
/src/main.c
|
/src/main.c
|
||||||
|
*.o
|
||||||
|
|||||||
@@ -1,18 +1,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FILE* in;
|
|
||||||
FILE* out;
|
|
||||||
FILE* err;
|
|
||||||
|
|
||||||
// OS-dependent handle to the process
|
uint64_t userdata;
|
||||||
uint32_t _proc_hdl;
|
FILE* in;
|
||||||
|
FILE* out;
|
||||||
} uniproc_process;
|
FILE* err;
|
||||||
|
|
||||||
uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, const char** argv);
|
// OS-dependent handle to the process
|
||||||
void uniproc_await_processes(uniproc_process* p, int* return_codes, size_t num_processes);
|
uint32_t _proc_hdl;
|
||||||
void uniproc_close_process(uniproc_process* p);
|
|
||||||
|
} uniproc_process;
|
||||||
|
|
||||||
|
uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, const char** argv);
|
||||||
|
void uniproc_await_processes(const uniproc_process* p, int* return_codes, const size_t num_processes);
|
||||||
|
void uniproc_close_process(uniproc_process* p);
|
||||||
|
int uniproc_are_processes_finished(const uniproc_process* p, const size_t num_processes);
|
||||||
|
void uniproc_nullify_processes(uniproc_process* p, const size_t num_processes);
|
||||||
|
int uniproc_is_process_null(const uniproc_process* p);
|
||||||
|
void uniproc_await_any_processes(const uniproc_process* p, const size_t num_processes);
|
||||||
|
void uniproc_set_userdata(uniproc_process* p, void const* userdata);
|
||||||
|
void* uniproc_get_userdata(uniproc_process* p);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -9,37 +9,59 @@
|
|||||||
uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, const char** argv)
|
uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, const char** argv)
|
||||||
{
|
{
|
||||||
(void)num_args;
|
(void)num_args;
|
||||||
|
uniproc_process p;
|
||||||
|
|
||||||
// Create pipes
|
// Create pipes
|
||||||
int stdin_pipe[2];
|
int stdin_pipe[2];
|
||||||
int stdout_pipe[2];
|
int stdout_pipe[2];
|
||||||
int stderr_pipe[2];
|
int stderr_pipe[2];
|
||||||
|
|
||||||
if (pipe(stdin_pipe) == -1)
|
if (pipe(stdin_pipe) == -1)
|
||||||
exit(EXIT_FAILURE);
|
{
|
||||||
|
uniproc_nullify_processes(&p, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
if (pipe(stdout_pipe) == -1)
|
if (pipe(stdout_pipe) == -1)
|
||||||
exit(EXIT_FAILURE);
|
{
|
||||||
|
uniproc_nullify_processes(&p, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
if (pipe(stderr_pipe) == -1)
|
if (pipe(stderr_pipe) == -1)
|
||||||
exit(EXIT_FAILURE);
|
{
|
||||||
|
uniproc_nullify_processes(&p, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
// Fork process
|
// Fork process
|
||||||
uniproc_process p;
|
|
||||||
p.in = stdin_pipe[1]; // Write handle
|
p.in = stdin_pipe[1]; // Write handle
|
||||||
p.out = stdout_pipe[0]; // Read handle
|
p.out = stdout_pipe[0]; // Read handle
|
||||||
p.err = stderr_pipe[0]; // Read handle
|
p.err = stderr_pipe[0]; // Read handle
|
||||||
|
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
exit(EXIT_FAILURE);
|
{
|
||||||
|
uniproc_nullify_processes(&p, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
// Child
|
// Child
|
||||||
else if (pid == 0)
|
else if (pid == 0)
|
||||||
{
|
{
|
||||||
// Redirect the child's std. files to the pipes created above
|
// Redirect the child's std. files to the pipes created above
|
||||||
if (dup2(stdin_pipe[0], STDIN_FILENO) == -1)
|
if (dup2(stdin_pipe[0], STDIN_FILENO) == -1)
|
||||||
exit(EXIT_FAILURE);
|
{
|
||||||
|
uniproc_nullify_processes(&p, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
if (dup2(stdout_pipe[1], STDOUT_FILENO) == -1)
|
if (dup2(stdout_pipe[1], STDOUT_FILENO) == -1)
|
||||||
exit(EXIT_FAILURE);
|
{
|
||||||
|
uniproc_nullify_processes(&p, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
if (dup2(stdout_pipe[2], STDERR_FILENO) == -1)
|
if (dup2(stdout_pipe[2], STDERR_FILENO) == -1)
|
||||||
exit(EXIT_FAILURE);
|
{
|
||||||
|
uniproc_nullify_processes(&p, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
// Close file handle references that are not needed
|
// Close file handle references that are not needed
|
||||||
if (stdin_pipe[0] != -1) close(stdin_pipe[0]);
|
if (stdin_pipe[0] != -1) close(stdin_pipe[0]);
|
||||||
@@ -51,7 +73,11 @@ uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, c
|
|||||||
|
|
||||||
// And execute the command provided
|
// And execute the command provided
|
||||||
if (execvp(cmd, argv) == -1)
|
if (execvp(cmd, argv) == -1)
|
||||||
exit(EXIT_FAILURE);
|
{
|
||||||
|
uniproc_nullify_processes(&p, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// Parent
|
// Parent
|
||||||
else
|
else
|
||||||
@@ -77,19 +103,50 @@ void uniproc_await_processes(uniproc_process* p, int* return_codes, size_t num_p
|
|||||||
int rc;
|
int rc;
|
||||||
if (return_codes == NULL)
|
if (return_codes == NULL)
|
||||||
for (size_t i = 0; i < num_processes; ++i)
|
for (size_t i = 0; i < num_processes; ++i)
|
||||||
waitpid(p._proc_hdl, &rc, 0);
|
if (!uniproc_is_process_null(p+i))
|
||||||
|
waitpid(p[i]._proc_hdl, &rc, 0);
|
||||||
else
|
else
|
||||||
for (size_t i = 0; i < num_processes; ++i)
|
for (size_t i = 0; i < num_processes; ++i)
|
||||||
waitpid(p._proc_hdl, return_codes+i, 0);
|
if (!uniproc_is_process_null(p+i))
|
||||||
|
waitpid(p[i]._proc_hdl, return_codes + i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uniproc_close_process(uniproc_process* p)
|
void uniproc_close_process(uniproc_process* p)
|
||||||
{
|
{
|
||||||
|
if (uniproc_is_process_null(p)) return;
|
||||||
kill(p->_proc_hdl, SIGKILL);
|
kill(p->_proc_hdl, SIGKILL);
|
||||||
fclose(p->in);
|
fclose(p->in);
|
||||||
fclose(p->out);
|
fclose(p->out);
|
||||||
fclose(p->err);
|
fclose(p->err);
|
||||||
|
uniproc_nullify_processes(p, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uniproc_are_processes_finished(const uniproc_process* p, const size_t num_processes)
|
||||||
|
{
|
||||||
|
int res = 1;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_processes; ++i)
|
||||||
|
res &&= uniproc_is_process_null(p + i) || waitpid(p[i]._proc_hdl, nullptr, WNOHANG | WIFEXITED | WIFSIGNALED | WCOREDUMP);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uniproc_nullify_processes(uniproc_process* p, const size_t num_processes)
|
||||||
|
{ memset(p, 0, sizeof(uniproc_process) * mum_processes); }
|
||||||
|
|
||||||
|
int 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)
|
||||||
|
{
|
||||||
|
while (uniproc_are_processes_finished(p, num_processes))
|
||||||
|
waitpid(0, nullptr, WIFEXITED | WIFSIGNALED | WCOREDUMP);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
#endif
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, const char** argv)
|
uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, const char** argv)
|
||||||
{
|
{
|
||||||
|
uniproc_process p;
|
||||||
|
|
||||||
// Create pipes
|
// Create pipes
|
||||||
HANDLE child_in;
|
HANDLE child_in;
|
||||||
HANDLE in;
|
HANDLE in;
|
||||||
@@ -21,22 +23,62 @@ uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, c
|
|||||||
|
|
||||||
// Actually create the pipes
|
// Actually create the pipes
|
||||||
if (!CreatePipe(&out, &child_out, &pipe_attribs, 0))
|
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))
|
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))
|
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
|
// Unset inherrit flags for the pipes
|
||||||
if (!SetHandleInformation(out, HANDLE_FLAG_INHERIT, 0))
|
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))
|
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))
|
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;
|
|
||||||
|
|
||||||
// Create p_cmd by appending all argv's to cmd
|
// Create p_cmd by appending all argv's to cmd
|
||||||
size_t x = strlen(cmd);
|
size_t x = strlen(cmd);
|
||||||
@@ -82,7 +124,16 @@ uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, c
|
|||||||
free(p_cmd);
|
free(p_cmd);
|
||||||
|
|
||||||
if (!is_ok)
|
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.err = _fdopen(_open_osfhandle((intptr_t)err, _O_RDONLY), "r");
|
||||||
p.out = _fdopen(_open_osfhandle((intptr_t)out, _O_RDONLY), "r");
|
p.out = _fdopen(_open_osfhandle((intptr_t)out, _O_RDONLY), "r");
|
||||||
@@ -97,27 +148,79 @@ uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, c
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uniproc_await_processes(uniproc_process* p, int* return_codes, size_t num_processes)
|
void uniproc_await_processes(const uniproc_process* p, int* return_codes, const size_t num_processes)
|
||||||
{
|
{
|
||||||
|
size_t num_valid_handles = 0;
|
||||||
HANDLE* h = (HANDLE*)malloc(num_processes*sizeof(HANDLE));
|
HANDLE* h = (HANDLE*)malloc(num_processes*sizeof(HANDLE));
|
||||||
for (size_t i = 0; i < num_processes; ++i)
|
for (size_t i = 0; i < num_processes; ++i)
|
||||||
h[i] = (HANDLE)p[i]._proc_hdl;
|
{
|
||||||
|
if (uniproc_is_process_null(p + i)) continue;
|
||||||
WaitForMultipleObjects(num_processes, h, 1, INFINITE);
|
h[num_valid_handles++] = (HANDLE)p[i]._proc_hdl;
|
||||||
|
}
|
||||||
|
if (num_valid_handles == 0) return;
|
||||||
|
WaitForMultipleObjects(num_valid_handles, h, 1, INFINITE);
|
||||||
free(h);
|
free(h);
|
||||||
|
|
||||||
if (return_codes == NULL) return;
|
if (return_codes == NULL) return;
|
||||||
for (size_t i = 0; i < num_processes; ++i)
|
for (size_t i = 0; i < num_processes; ++i)
|
||||||
GetExitCodeProcess((HANDLE)p[i]._proc_hdl, (LPDWORD)(return_codes+i));
|
{
|
||||||
|
if (uniproc_is_process_null(p + i)) continue;
|
||||||
|
GetExitCodeProcess((HANDLE)p[i]._proc_hdl, (LPDWORD)(return_codes + i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uniproc_close_process(uniproc_process* p)
|
void uniproc_close_process(uniproc_process* p)
|
||||||
{
|
{
|
||||||
|
if (uniproc_is_process_null(p)) return;
|
||||||
TerminateProcess((HANDLE)p->_proc_hdl, 2);
|
TerminateProcess((HANDLE)p->_proc_hdl, 2);
|
||||||
CloseHandle((HANDLE)p->_proc_hdl);
|
CloseHandle((HANDLE)p->_proc_hdl);
|
||||||
fclose(p->in);
|
fclose(p->in);
|
||||||
fclose(p->out);
|
fclose(p->out);
|
||||||
fclose(p->err);
|
fclose(p->err);
|
||||||
|
uniproc_nullify_processes(p, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uniproc_are_processes_finished(const uniproc_process* p, const size_t num_processes)
|
||||||
|
{
|
||||||
|
HANDLE* h = (HANDLE*)malloc(num_processes*sizeof(HANDLE));
|
||||||
|
size_t num_valid_handles = 0;
|
||||||
|
for (size_t i = 0; i < num_processes; ++i)
|
||||||
|
{
|
||||||
|
if (uniproc_is_process_null(p + i)) continue;
|
||||||
|
h[i] = (HANDLE)p[i]._proc_hdl;
|
||||||
|
num_valid_handles++;
|
||||||
|
}
|
||||||
|
if (num_valid_handles == 0) return 1;
|
||||||
|
DWORD ret = WaitForMultipleObjects(num_valid_handles, h, 1, 0);
|
||||||
|
free(h);
|
||||||
|
return ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + num_valid_handles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uniproc_nullify_processes(uniproc_process* p, const size_t num_processes)
|
||||||
|
{ memset(p, 0, num_processes * sizeof(uniproc_process)); }
|
||||||
|
|
||||||
|
int 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));
|
||||||
|
size_t num_valid_handles = 0;
|
||||||
|
for (size_t i = 0; i < num_processes; ++i)
|
||||||
|
{
|
||||||
|
if (uniproc_is_process_null(p + i)) continue;
|
||||||
|
h[i] = (HANDLE)p[i]._proc_hdl;
|
||||||
|
num_valid_handles++;
|
||||||
|
}
|
||||||
|
if (num_valid_handles == 0) return;
|
||||||
|
WaitForMultipleObjects(num_valid_handles, h, 0, INFINITE);
|
||||||
|
free(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
#endif
|
||||||
Reference in New Issue
Block a user