Implemented windows implementation of uniproc

This commit is contained in:
2025-03-02 22:46:22 +11:00
parent 9cc6d81a9f
commit d47f6be401
3 changed files with 141 additions and 0 deletions

13
.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
################################################################################
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################
/.vs/uniproc/FileContentIndex
/.vs/uniproc/v17/ipch/AutoPCH
/.vs
/CppProperties.json
/include/tmp.cpp
/test.exe
/test.ilk
/test.pdb
/src/main.c

18
include/uniproc.h Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <Windows.h>
typedef struct {
FILE* in;
FILE* out;
FILE* err;
// OS-dependent handle to the process
uint32_t _proc_hdl;
} uniproc_process;
uniproc_process uniproc_create_process(const char* cmd);
void uniproc_await_processes(uniproc_process* p, int* return_codes, size_t num_processes);
void uniproc_close_process(uniproc_process* p);

110
src/uniproc_win64.c Normal file
View File

@@ -0,0 +1,110 @@
#if defined(_WIN32) || defined(_WIN64)
#include "uniproc.h"
#include <Windows.h>
#include <fcntl.h>
#include <io.h>
uniproc_process uniproc_create_process(const char* cmd)
{
// Create pipes
HANDLE child_in;
HANDLE in;
HANDLE child_out;
HANDLE out;
HANDLE child_err;
HANDLE err;
SECURITY_ATTRIBUTES pipe_attribs;
pipe_attribs.nLength = sizeof(SECURITY_ATTRIBUTES);
pipe_attribs.bInheritHandle = 1;
pipe_attribs.lpSecurityDescriptor = NULL;
// Actually create the pipes
if (!CreatePipe(&out, &child_out, &pipe_attribs, 0))
exit(EXIT_FAILURE);
if (!CreatePipe(&err, &child_err, &pipe_attribs, 0))
exit(EXIT_FAILURE);
if (!CreatePipe(&child_in, &in, &pipe_attribs, 0))
exit(EXIT_FAILURE);
// Unset inherrit flags for the pipes
if (!SetHandleInformation(out, HANDLE_FLAG_INHERIT, 0))
exit(EXIT_FAILURE);
if (!SetHandleInformation(err, HANDLE_FLAG_INHERIT, 0))
exit(EXIT_FAILURE);
if (!SetHandleInformation(in, HANDLE_FLAG_INHERIT, 0))
exit(EXIT_FAILURE);
// Create child process
uniproc_process p;
size_t cmd_len = strlen(cmd);
char* p_cmd = malloc((cmd_len+1) * sizeof(char));
memcpy(p_cmd, cmd, cmd_len * sizeof(char));
p_cmd[cmd_len] = '\0';
PROCESS_INFORMATION p_info;
STARTUPINFOA p_startup;
memset(&p_info, 0, sizeof(PROCESS_INFORMATION));
memset(&p_startup, 0, sizeof(STARTUPINFOA));
p_startup.cb = sizeof(STARTUPINFOA);
p_startup.dwFlags |= STARTF_USESTDHANDLES;
p_startup.hStdInput = child_in;
p_startup.hStdOutput = child_out;
p_startup.hStdError = child_err;
int is_ok = CreateProcessA(
NULL,// Application name
p_cmd, // Command to execute
NULL,// Security attributes
NULL,// Primary thread security
1, // Inherrit handles
0, // Creation flags
NULL,// Environment (use parent's)
NULL,// Current directory (use parent's)
&p_startup,
&p_info
);
free(p_cmd);
if (!is_ok)
exit(EXIT_FAILURE);
p.err = _fdopen(_open_osfhandle((intptr_t)err, _O_RDONLY), "r");
p.out = _fdopen(_open_osfhandle((intptr_t)out, _O_RDONLY), "r");
p.in = _fdopen(_open_osfhandle( (intptr_t)in, _O_WRONLY), "w");
p._proc_hdl = (uint32_t)p_info.hProcess;
CloseHandle(child_in);
CloseHandle(child_out);
CloseHandle(child_err);
CloseHandle(p_info.hThread);
return p;
}
void uniproc_await_processes(uniproc_process* p, int* return_codes, size_t num_processes)
{
HANDLE* h = (HANDLE*)malloc(num_processes*sizeof(HANDLE));
for (size_t i = 0; i < num_processes; ++i)
h[i] = (HANDLE)p[i]._proc_hdl;
WaitForMultipleObjects(num_processes, h, 1, INFINITE);
free(h);
if (return_codes == NULL) return;
for (size_t i = 0; i < num_processes; ++i)
GetExitCodeProcess((HANDLE)p[i]._proc_hdl, (LPDWORD)(return_codes+i));
}
void uniproc_close_process(uniproc_process* p)
{
fclose(p->in);
fclose(p->out);
fclose(p->err);
CloseHandle((HANDLE)p->_proc_hdl);
}
#endif