[rcore] add process execution functions for posix systems

This commit is contained in:
moe li 2026-04-29 19:28:48 +08:00
parent ccc0d7452a
commit 24b36efbdc
2 changed files with 166 additions and 0 deletions

View File

@ -961,6 +961,12 @@ typedef enum {
NPATCH_THREE_PATCH_HORIZONTAL // Npatch layout: 3x1 tiles
} NPatchLayout;
// Process info
typedef struct Process {
int pid; // Process unique identifier
int exitCode; // Process exit code
} Process;
// Callbacks to hook some internal functions
// WARNING: These callbacks are intended for advanced users
typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
@ -1241,6 +1247,13 @@ RLAPI Vector2 GetTouchPosition(int index); // Get touch posit
RLAPI int GetTouchPointId(int index); // Get touch point identifier for given index
RLAPI int GetTouchPointCount(void); // Get number of touch points
// Process execution functions
RLAPI Process InitProcess(const char *command, char *const args[]); // Initialize a new process, returns a Process struct
RLAPI bool CheckProcess(Process *process); // Check if a process is still running, updates Process struct
RLAPI void PauseProcess(Process *process); // Pause process execution
RLAPI void ResumeProcess(Process *process); // Resume paused process execution
RLAPI void CloseProcess(Process *process); // Close process and free resources
//------------------------------------------------------------------------------------
// Gestures and Touch Handling Functions (Module: rgestures)
//------------------------------------------------------------------------------------

View File

@ -210,6 +210,12 @@
#define ACCESS(fn) access(fn, F_OK)
#endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
#include <sys/wait.h> // Required for: waitpid() [Used in CheckProcess()]
#include <signal.h> // Required for: kill() [Used in PauseProcess(), ResumeProcess(), CloseProcess()]
#include <sys/types.h> // Required for: pid_t [Used as function local variable type and for Process PID type]
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@ -4211,6 +4217,153 @@ int GetTouchPointCount(void)
return CORE.Input.Touch.pointCount;
}
//----------------------------------------------------------------------------------
// Module Functions Definition: Process Execution
//----------------------------------------------------------------------------------
// Initialize a new process, returns a Process struct
RLAPI Process InitProcess(const char *command, char *const args[])
{
// The last element of the args array must be NULL
Process process = { 0 };
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
pid_t pid = fork();
if (pid < 0)
{
TRACELOG(LOG_WARNING, "PROCESS: Failed to create process");
}
else if (pid == 0)
{
// Child process
execvp(command, args);
// If execvp returns, it must have failed
_exit(1);
}
else
{
process.pid = pid;
}
#else
TRACELOG(LOG_WARNING, "PROCESS: Process management not supported on this platform");
#endif
return process;
}
// Check if a process is still running, updates Process struct
RLAPI bool CheckProcess(Process *process)
{
if ((process == NULL) || (process->pid <= 0))
{
return false;
}
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
int status = 0;
pid_t result = waitpid(process->pid, &status, WNOHANG);
if (result == 0)
{
// Still running
return true;
}
else if (result == process->pid)
{
// Not running
if (WIFEXITED(status))
{
process->exitCode = WEXITSTATUS(status);
}
else if (WIFSIGNALED(status))
{
// Terminated by signal
process->exitCode = -1;
}
// Mark as completed
process->pid = 0;
return false;
}
else
{
// Error occurred
TRACELOG(LOG_WARNING, "PROCESS: Failed to check process status");
return false;
}
#else
TRACELOG(LOG_WARNING, "PROCESS: Process management not supported on this platform");
#endif
return false;
}
// Pause process execution
RLAPI void PauseProcess(Process *process)
{
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
if (kill(process->pid, SIGSTOP) != 0)
{
TRACELOG(LOG_WARNING, "PROCESS: Failed to pause process");
}
#else
TRACELOG(LOG_WARNING, "PROCESS: Process management not supported on this platform");
#endif
}
// Resume paused process execution
RLAPI void ResumeProcess(Process *process)
{
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
if (kill(process->pid, SIGCONT) != 0)
{
TRACELOG(LOG_WARNING, "PROCESS: Failed to resume process");
}
#else
TRACELOG(LOG_WARNING, "PROCESS: Process management not supported on this platform");
#endif
}
// Close process and free resources
RLAPI void CloseProcess(Process *process)
{
if ((process == NULL) || (process->pid <= 0))
{
return;
}
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
if (!CheckProcess(process))
{
return;
}
// In case that the process is paused
kill(process->pid, SIGCONT);
if (kill(process->pid, SIGTERM) != 0)
{
TRACELOG(LOG_WARNING, "PROCESS: Failed to terminate process");
// Kill the process anyway
kill(process->pid, SIGKILL);
}
// Wait process termination
waitpid(process->pid, NULL, 0);
// Align as CheckProcess() would do for a killed process
process->exitCode = -1;
process->pid = 0;
#else
TRACELOG(LOG_WARNING, "PROCESS: Process management not supported on this platform");
#endif
}
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------