2022-04-05 10:11:19 +00:00
/***
Copyright ( C ) 2021 J Reece Wilson ( a / k / a " Reece " ) . All rights reserved .
2022-12-16 00:41:01 +00:00
File : AuProcess . Unix . cpp
2022-04-05 10:11:19 +00:00
File : Process . Linux . cpp
Date : 2021 - 6 - 12
Author : Reece
* * */
# include <RuntimeInternal.hpp>
2022-12-16 00:41:01 +00:00
# include "AuProcesses.hpp"
# include "AuProcess.Unix.hpp"
2022-04-05 10:11:19 +00:00
# include <unistd.h>
# include <fcntl.h>
# include <sys/syscall.h>
# include <sys/types.h>
# include <sys/wait.h>
2022-04-05 10:18:35 +00:00
2022-12-16 00:41:01 +00:00
# include <Source/Threading/Primitives/AuSemaphore.Unix.hpp>
2023-09-14 23:11:14 +00:00
# include <Source/IO/AuIOHandle.Unix.hpp>
2022-08-10 15:04:41 +00:00
2023-08-30 00:28:05 +00:00
# if defined(AURORA_COMPILER_CLANG)
// warning: enumeration values 'kEnumCount' and 'kEnumInvalid' not handled in switch [-Wswitch
# pragma clang diagnostic ignored "-Wswitch"
// Yea, I don't give a shit.
# endif
2022-08-10 15:36:03 +00:00
# if defined(AURORA_IS_LINUX_DERIVED)
# include <sys/prctl.h>
# include <setjmp.h>
# if !defined(CLONE_CLEAR_SIGHAND)
# define CLONE_CLEAR_SIGHAND 0x100000000ULL
# endif
2022-08-10 15:04:41 +00:00
# endif
2022-04-05 10:11:19 +00:00
2023-09-16 20:49:30 +00:00
# if defined(AURORA_PLATFORM_BSD)
# if defined(__FreeBSD__)
# include <sys/param.h>
# endif
# include <sys/cpuset.h>
# endif
# if defined(AURORA_IS_LINUX_DERIVED)
# include <sched.h>
# endif
2022-04-05 10:11:19 +00:00
namespace Aurora : : Processes
{
2022-04-05 10:24:48 +00:00
static AuThreadPrimitives : : RWLockUnique_t gRWLock ;
2022-04-05 10:11:19 +00:00
static AuHashMap < pid_t , ProcessImpl * > gPidLookupMap ;
2022-06-11 23:52:46 +00:00
struct ProcessAliveLoopSource : AuLoop : : LSEvent
2022-05-04 19:34:46 +00:00
{
ProcessAliveLoopSource ( ) ;
virtual AuLoop : : ELoopSource GetType ( ) override ;
} ;
ProcessAliveLoopSource : : ProcessAliveLoopSource ( ) : LSEvent ( false , false , true )
{ }
AuLoop : : ELoopSource ProcessAliveLoopSource : : GetType ( )
{
return AuLoop : : ELoopSource : : eProcessDead ;
}
2023-08-21 16:48:42 +00:00
ProcessImpl : : ProcessImpl ( StartupParameters & & params ) : startup_ ( AuMove ( params ) )
2022-04-05 10:11:19 +00:00
{
AuIOFS : : NormalizePath ( this - > startup_ . process , this - > startup_ . process ) ;
2022-08-10 15:04:41 +00:00
if ( this - > startup_ . workingDirectory )
{
AuString a ;
AuIOFS : : NormalizePath ( a , this - > startup_ . workingDirectory . value ( ) ) ;
this - > startup_ . workingDirectory = a ;
}
2022-04-05 10:11:19 +00:00
this - > startup_ . args . insert ( startup_ . args . begin ( ) , startup_ . process ) ;
for ( const auto & arg : this - > startup_ . args )
{
this - > cargs_ . push_back ( arg . c_str ( ) ) ;
this - > debug_ + = arg + " " ;
}
this - > cargs_ . push_back ( nullptr ) ;
if ( this - > debug_ . size ( ) )
{
this - > debug_ . resize ( this - > debug_ . size ( ) - 1 ) ;
}
2022-04-13 14:43:38 +00:00
this - > type_ = this - > startup_ . type ;
2022-04-05 10:11:19 +00:00
}
ProcessImpl : : ~ ProcessImpl ( )
{
if ( this - > type_ = = ESpawnType : : eSpawnChildProcessWorker )
{
TryKill ( ) ;
Terminate ( ) ;
}
{
2022-04-05 10:24:48 +00:00
AU_LOCK_GUARD ( gRWLock - > AsWritable ( ) ) ;
2022-04-05 10:11:19 +00:00
2022-04-05 10:18:35 +00:00
if ( this - > alive_ )
2022-04-05 10:11:19 +00:00
{
2022-04-05 10:18:35 +00:00
if ( this - > type_ = = ESpawnType : : eSpawnThreadLeader )
{
: : kill ( this - > pidt_ , SIGCONT ) ;
}
2022-04-05 10:11:19 +00:00
}
2022-04-05 10:18:35 +00:00
AuTryRemove ( gPidLookupMap , this - > pidt_ ) ;
2022-04-05 10:11:19 +00:00
}
ShutdownPipes ( ) ;
}
AuUInt ProcessImpl : : GetProcessId ( )
{
return this - > pidt_ ;
}
void ProcessImpl : : ByeLol ( AuSInt code )
{
this - > exitCode_ = code ;
if ( this - > finished_ )
{
this - > finished_ - > Set ( ) ;
}
2022-05-04 19:34:46 +00:00
if ( this - > loopSource_ )
{
this - > loopSource_ - > Set ( ) ;
}
2022-04-05 10:11:19 +00:00
}
void ProcessImpl : : ShutdownPipes ( )
{
2022-06-23 12:25:20 +00:00
if ( ! this - > bDontRelOut_ )
{
if ( auto fd = AuExchange ( pipeStdOut_ [ 1 ] , { } ) )
{
: : close ( fd ) ;
}
}
if ( ! this - > bDontRelErr_ )
{
if ( auto fd = AuExchange ( pipeStdErr_ [ 1 ] , { } ) )
{
: : close ( fd ) ;
}
}
if ( ! this - > bDontRelIn_ )
{
if ( auto fd = AuExchange ( pipeStdIn_ [ 0 ] , { } ) )
{
: : close ( fd ) ;
}
}
2022-04-05 10:11:19 +00:00
}
bool ProcessImpl : : TryKill ( )
{
2022-04-05 10:24:48 +00:00
AU_LOCK_GUARD ( gRWLock - > AsReadable ( ) ) ;
2022-04-05 10:18:35 +00:00
2022-04-05 10:11:19 +00:00
if ( this - > alive_ )
{
2022-05-04 15:34:02 +00:00
if ( : : kill ( this - > pidt_ , SIGTERM ) = = 0 )
{
2023-08-11 15:51:42 +00:00
return this - > finished_ - > LockMS ( 500 ) ;
2022-05-04 15:34:02 +00:00
}
2022-04-05 10:11:19 +00:00
}
2022-04-05 10:18:35 +00:00
2022-04-05 10:11:19 +00:00
return true ;
}
bool ProcessImpl : : Terminate ( )
{
2022-04-05 10:24:48 +00:00
AU_LOCK_GUARD ( gRWLock - > AsReadable ( ) ) ;
2022-04-05 10:18:35 +00:00
2022-04-05 10:11:19 +00:00
if ( this - > alive_ )
{
return : : kill ( this - > pidt_ , SIGKILL ) = = 0 ;
}
2022-04-05 10:18:35 +00:00
2022-04-05 10:11:19 +00:00
return true ;
}
AuSPtr < Aurora : : Threading : : IWaitable > ProcessImpl : : AsWaitable ( )
{
return this - > finished_ ;
}
2022-06-12 13:53:35 +00:00
AuSPtr < AuLoop : : ILoopSource > ProcessImpl : : AsLoopSource ( )
2022-05-04 19:34:46 +00:00
{
return this - > loopSource_ ;
}
2022-04-05 10:11:19 +00:00
AuSInt ProcessImpl : : GetExitCode ( )
{
return this - > exitCode_ ;
}
bool ProcessImpl : : Read ( EStandardHandle stream , const AuMemoryViewStreamWrite & destination , bool nonblock )
{
2023-09-15 14:53:20 +00:00
if ( ! IO : : EStandardStreamIsValid ( stream ) | | ( stream = = EStandardHandle : : eInputStream ) )
{
SysPushErrorArg ( " Invalid Stream " ) ;
return false ;
}
if ( ! destination )
{
SysPushErrorArg ( ) ;
return false ;
}
auto handle = stream = = EStandardHandle : : eErrorStream ? this - > pipeStdErr_ [ 0 ] : this - > pipeStdOut_ [ 0 ] ;
2022-04-05 10:11:19 +00:00
if ( handle < 0 )
{
2022-04-13 14:43:38 +00:00
SysPushErrorUninitialized ( ) ;
2022-04-05 10:11:19 +00:00
return false ;
}
2022-05-04 15:34:02 +00:00
auto control = : : fcntl ( handle , F_GETFL ) ;
2022-04-05 10:11:19 +00:00
auto ref = control ;
if ( nonblock )
{
control | = O_NONBLOCK ;
}
else
{
control & = ~ O_NONBLOCK ;
}
if ( ref ! = control )
{
2022-05-04 15:34:02 +00:00
: : fcntl ( handle , F_SETFL , control ) ;
2022-04-05 10:11:19 +00:00
}
2022-04-13 14:43:38 +00:00
int tmp ;
do
{
2022-05-04 15:34:02 +00:00
tmp = : : read ( handle , destination . ptr , destination . length ) ;
2023-09-14 23:11:14 +00:00
}
while ( ( tmp = = - 1 & & errno = = EINTR ) ) ;
2022-04-13 14:43:38 +00:00
if ( tmp < = 0 )
2022-04-05 10:11:19 +00:00
{
2022-04-15 14:46:07 +00:00
if ( tmp = = 0 )
2022-04-13 14:43:38 +00:00
{
2022-04-15 14:46:07 +00:00
return nonblock ;
2022-04-13 14:43:38 +00:00
}
2022-04-15 14:46:07 +00:00
SysPushErrorMem ( ) ;
2022-04-05 10:11:19 +00:00
return false ;
}
destination . outVariable = tmp ;
return true ;
}
bool ProcessImpl : : Write ( const AuMemoryViewStreamRead & source )
{
2022-04-05 10:18:35 +00:00
auto handle = this - > pipeStdIn_ [ 1 ] ;
2022-04-05 10:11:19 +00:00
if ( ! handle )
{
return false ;
}
2022-05-04 19:34:46 +00:00
auto control = : : fcntl ( handle , F_GETFL ) ;
auto ref = control ;
if ( /*nonblock*/ true )
{
control | = O_NONBLOCK ;
}
else
{
control & = ~ O_NONBLOCK ;
}
if ( ref ! = control )
{
: : fcntl ( handle , F_SETFL , control ) ;
}
return : : write ( handle , source . ptr , source . length ) = = source . length ;
2022-04-05 10:11:19 +00:00
}
2023-09-14 23:11:14 +00:00
static bool InitProcessStdHandles ( EStreamForward fwd , int * fds , AuIO : : EStandardStream stream , IO : : IIOHandle * pHandle )
2022-04-05 10:11:19 +00:00
{
2023-09-14 23:11:14 +00:00
AuOptionalEx < AuUInt64 > optHandle ;
bool bIsRead = stream = = AuIO : : EStandardStream : : eInputStream ;
2022-06-23 12:25:20 +00:00
switch ( fwd )
2022-04-05 10:11:19 +00:00
{
2023-09-14 23:11:14 +00:00
case EStreamForward : : eIOHandle :
optHandle = pHandle - > GetOSHandleSafe ( ) ;
if ( ! optHandle )
{
return false ;
}
if ( bIsRead )
{
fds [ 0 ] = dup ( ( int ) optHandle . value ( ) ) ;
}
else
{
fds [ 1 ] = dup ( ( int ) optHandle . value ( ) ) ;
}
break ;
2022-06-23 12:25:20 +00:00
case EStreamForward : : eCurrentProcess :
2023-09-14 23:11:14 +00:00
if ( stream = = AuIO : : EStandardStream : : eInputStream )
{
fds [ 0 ] = dup ( STDIN_FILENO ) ;
if ( fds [ 0 ] < 0 )
{
return false ;
}
}
else if ( stream = = AuIO : : EStandardStream : : eErrorStream )
{
fds [ 1 ] = dup ( STDERR_FILENO ) ;
if ( fds [ 1 ] < 0 )
{
return false ;
}
}
else if ( stream = = AuIO : : EStandardStream : : eOutputStream )
{
fds [ 1 ] = dup ( STDOUT_FILENO ) ;
if ( fds [ 1 ] < 0 )
{
return false ;
}
}
else
{
return false ;
}
2022-06-23 12:25:20 +00:00
break ;
case EStreamForward : : eAsyncPipe :
if ( : : pipe ( fds ) )
2022-04-05 10:11:19 +00:00
{
2022-04-13 14:43:38 +00:00
SysPushErrorMem ( ) ;
2022-04-05 10:11:19 +00:00
return false ;
}
2022-06-23 12:25:20 +00:00
break ;
case EStreamForward : : eNull :
2023-09-14 23:11:14 +00:00
if ( bIsRead )
{
fds [ 0 ] = : : open ( " /dev/null " , O_RDWR ) ;
}
else
{
fds [ 1 ] = : : open ( " /dev/null " , O_RDWR ) ;
}
2022-06-23 12:25:20 +00:00
break ;
2023-08-11 15:51:42 +00:00
case EStreamForward : : eNewConsoleWindow :
SysPushErrorGeneric ( " AuProcesses is not the right place for PTY support. At least not in this form (this level of abstraction only cares for pipes). " ) ;
2023-09-14 23:11:14 +00:00
return false ;
2022-04-05 10:11:19 +00:00
}
2023-09-14 23:11:14 +00:00
if ( fds [ 0 ] > 0 )
{
if ( ! AuIO : : SetFDShareAccess ( fds [ 0 ] , bIsRead ) )
{
return false ;
}
}
if ( fds [ 1 ] > 0 )
{
if ( ! AuIO : : SetFDShareAccess ( fds [ 1 ] , ! bIsRead ) )
{
return false ;
}
}
// Yea, I guess we can't really guard against threads racing to leak close on exec-less fds
// Let's just not care on UNIX.
// Worst case, we leak a daemons input/output FD to a different daemon of a differing permission level
// ...and somehow you can find that fd
// ...and probably dup it before ::start()
// ...and issue the right commands over the stream to do something bad
// Shouldn't need to worry about his for a while.
2022-06-23 12:25:20 +00:00
return true ;
}
2022-04-05 10:11:19 +00:00
2022-06-23 12:25:20 +00:00
bool ProcessImpl : : Init ( )
{
2023-09-14 23:11:14 +00:00
InitProcessStdHandles ( this - > startup_ . fwdOut , this - > pipeStdOut_ , AuIO : : EStandardStream : : eOutputStream , this - > startup_ . handleOutStream ) ;
InitProcessStdHandles ( this - > startup_ . fwdErr , this - > pipeStdErr_ , AuIO : : EStandardStream : : eErrorStream , this - > startup_ . handleErrorStream ) ;
InitProcessStdHandles ( this - > startup_ . fwdIn , this - > pipeStdIn_ , AuIO : : EStandardStream : : eInputStream , this - > startup_ . handleInputStream ) ;
2022-04-05 10:11:19 +00:00
2022-05-04 19:34:46 +00:00
this - > loopSource_ = AuMakeShared < ProcessAliveLoopSource > ( ) ;
if ( ! this - > loopSource_ )
{
return false ;
}
2022-04-05 10:11:19 +00:00
this - > finished_ = AuThreadPrimitives : : EventShared ( false , false , true ) ;
2022-05-04 19:34:46 +00:00
if ( ! this - > finished_ )
{
return false ;
}
2022-06-23 12:25:20 +00:00
if ( ( this - > startup_ . fwdIn = = EStreamForward : : eAsyncPipe ) | |
( this - > startup_ . fwdOut = = EStreamForward : : eAsyncPipe ) )
2022-05-04 19:34:46 +00:00
{
2023-08-11 15:51:42 +00:00
this - > fsHandle_ = AuIO : : IOHandleShared ( ) ;
2022-05-04 19:34:46 +00:00
if ( ! this - > fsHandle_ )
{
return false ;
}
this - > fsStream_ = AuMakeShared < ProcessPipeFileStream > ( ) ;
if ( ! this - > fsStream_ )
{
return false ;
}
2023-09-14 23:11:14 +00:00
this - > fsHandle_ - > InitFromPairMove ( this - > pipeStdOut_ [ 0 ] = = - 1 ? AuOptionalEx < AuUInt64 > { } : AuOptionalEx < AuUInt64 > { ( AuUInt64 ) this - > pipeStdOut_ [ 0 ] } ,
this - > pipeStdIn_ [ 1 ] = = - 1 ? AuOptionalEx < AuUInt64 > { } : AuOptionalEx < AuUInt64 > { ( AuUInt64 ) this - > pipeStdIn_ [ 1 ] } ) ;
2022-05-04 19:34:46 +00:00
this - > fsStream_ - > Init ( this - > fsHandle_ ) ;
}
2022-06-23 12:25:20 +00:00
if ( this - > startup_ . fwdErr = = EStreamForward : : eAsyncPipe )
2022-05-04 19:34:46 +00:00
{
2023-08-11 15:51:42 +00:00
this - > fsErrorHandle_ = AuIO : : IOHandleShared ( ) ;
2022-05-04 19:34:46 +00:00
if ( ! this - > fsErrorHandle_ )
{
return false ;
}
this - > fsErrorStream_ = AuMakeShared < ProcessPipeFileStream > ( ) ;
if ( ! this - > fsErrorStream_ )
{
return false ;
}
2023-09-14 23:11:14 +00:00
this - > fsErrorHandle_ - > InitFromPairMove ( this - > pipeStdErr_ [ 0 ] = = - 1 ? AuOptionalEx < AuUInt64 > { } : AuOptionalEx < AuUInt64 > { ( AuUInt64 ) this - > pipeStdErr_ [ 0 ] } , { } ) ;
2022-05-04 19:34:46 +00:00
this - > fsErrorStream_ - > Init ( this - > fsErrorHandle_ ) ;
}
return true ;
2022-04-05 10:11:19 +00:00
}
2022-05-12 08:04:32 +00:00
AuSPtr < AuIO : : IAsyncTransaction > ProcessImpl : : NewAsyncTransaction ( )
2022-05-04 15:34:02 +00:00
{
2022-05-13 00:43:54 +00:00
return this - > fsStream_ ? this - > fsStream_ - > NewTransaction ( ) : AuSPtr < AuIO : : IAsyncTransaction > { } ;
2022-05-04 15:34:02 +00:00
}
2022-05-12 08:04:32 +00:00
AuSPtr < AuIO : : IAsyncTransaction > ProcessImpl : : NewErrorStreamAsyncTransaction ( )
2022-05-04 15:34:02 +00:00
{
2022-05-13 00:43:54 +00:00
return this - > fsErrorStream_ ? this - > fsErrorStream_ - > NewTransaction ( ) : AuSPtr < AuIO : : IAsyncTransaction > { } ;
2022-05-04 15:34:02 +00:00
}
2023-09-16 21:08:10 +00:00
AuSPtr < IO : : IIOHandle > ProcessImpl : : GetOutputAndInputHandles ( )
{
return this - > fsHandle_ ;
}
AuSPtr < IO : : IIOHandle > ProcessImpl : : GetErrorStreamHandle ( )
{
return this - > fsErrorHandle_ ;
}
2022-08-10 15:04:41 +00:00
void ProcessImpl : : ForkMain ( )
{
{
2023-09-14 23:11:14 +00:00
: : dup2 ( this - > pipeStdIn_ [ 0 ] , STDIN_FILENO ) ;
: : close ( this - > pipeStdIn_ [ 0 ] ) ;
2022-08-10 15:04:41 +00:00
}
{
2023-09-14 23:11:14 +00:00
: : dup2 ( this - > pipeStdErr_ [ 1 ] , STDERR_FILENO ) ;
: : close ( this - > pipeStdErr_ [ 1 ] ) ;
2022-08-10 15:04:41 +00:00
}
{
2023-09-14 23:11:14 +00:00
: : dup2 ( this - > pipeStdOut_ [ 1 ] , STDOUT_FILENO ) ;
: : close ( this - > pipeStdOut_ [ 1 ] ) ;
2022-08-10 15:04:41 +00:00
}
2022-08-10 15:36:03 +00:00
# if defined(AURORA_IS_LINUX_DERIVED)
if ( this - > type_ = = ESpawnType : : eSpawnChildProcessWorker )
2022-08-10 15:04:41 +00:00
{
2022-08-10 15:36:03 +00:00
: : prctl ( PR_SET_PDEATHSIG , SIGTERM ) ;
2022-08-10 15:04:41 +00:00
}
2022-08-10 15:36:03 +00:00
# endif
2023-09-15 15:03:41 +00:00
if ( this - > type_ ! = ESpawnType : : eSpawnOvermap )
{
: : setsid ( ) ;
}
if ( ! this - > startup_ . bInheritEnvironmentVariables )
{
try
{
AuList < AuString > keys ;
for ( const auto & [ key , value ] : AuProcess : : EnvironmentGetAll ( ) )
{
keys . push_back ( key ) ;
}
2022-08-10 15:36:03 +00:00
2023-09-15 15:03:41 +00:00
AuProcess : : EnvironmentRemoveMany ( keys ) ;
}
catch ( . . . )
{
SysPanic ( " Couldn't fork " ) ;
}
}
if ( this - > startup_ . environmentVariables . size ( ) )
{
SysAssert ( AuProcess : : EnvironmentSetMany ( this - > startup_ . environmentVariables ) ) ;
}
2022-08-10 15:04:41 +00:00
# if defined(AURORA_IS_XNU_DERIVED)
if ( this - > startup_ . workingDirectory )
{
: : pthread_chdir_np ( this - > startup_ . workingDirectory . value ( ) . c_str ( ) ) ;
}
# else
if ( this - > startup_ . workingDirectory )
{
: : chroot ( this - > startup_ . workingDirectory . value ( ) . c_str ( ) ) ;
}
# endif
2023-09-16 20:49:30 +00:00
if ( this - > startup_ . optAffinity )
{
auto affinity = this - > startup_ . optAffinity . Value ( ) ;
# if defined(__FreeBSD__)
cpuset_setid ( CPU_WHICH_PID , - 1 , ( cpusetid_t * ) & affinity . lower ) ; // I guess?
# elif defined(AURORA_IS_LINUX_DERIVED) || (defined(AURORA_IS_POSIX_DERIVED) && defined(_GNU_SOURCE))
cpu_set_t cpuset ;
CPU_ZERO ( & cpuset ) ;
AuUInt8 index { } ;
while ( affinity . CpuBitScanForward ( index , index ) )
{
CPU_SET ( index , & cpuset ) ;
index + + ;
}
if ( ! CPU_COUNT ( & cpuset ) )
{
return ;
}
# if defined(AURORA_IS_LINUX_DERIVED)
sched_setaffinity ( 0 , sizeof ( cpu_set_t ) , & cpuset ) ;
# else
pthread_setaffinity_np ( pthread_self ( ) , cpuset_size ( cpuSet ) , & cpuset ) ;
# endif
# elif defined(AURORA_IS_POSIX_DERIVED)
if ( auto cpuSet = cpuset_alloc ( ) )
{
cpuset_init ( cpuSet ) ;
AuUInt8 index { } ;
while ( affinity . CpuBitScanForward ( index , index ) )
{
cpuset_set_cpu ( cpuSet , index , 1 ) ;
index + + ;
}
pthread_setaffinity_np ( pthread_self ( ) , cpuset_size ( cpuSet ) , cpuSet ) ;
cpuset_free ( cpuSet ) ;
}
# else
// Who else?
# endif
}
2022-08-10 15:04:41 +00:00
: : execv ( this - > startup_ . process . c_str ( ) , ( char * const * ) this - > cargs_ . data ( ) ) ; // https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html
SysPushErrorGen ( " execv didn't overwrite the process map. Launch: {} ({}) " , this - > startup_ . process , this - > debug_ ) ;
}
2022-04-05 10:11:19 +00:00
bool ProcessImpl : : Start ( )
{
this - > exitCode_ = 0x10110100 ;
if ( this - > type_ = = ESpawnType : : eSpawnOvermap )
{
2023-09-14 23:11:14 +00:00
this - > ForkMain ( ) ;
2022-04-05 10:11:19 +00:00
return false ;
}
pid_t pid ;
{
2022-05-04 15:34:02 +00:00
pid = : : fork ( ) ;
2022-04-05 10:11:19 +00:00
if ( pid = = 0 )
{
2022-08-10 15:04:41 +00:00
this - > ForkMain ( ) ;
2023-09-23 07:15:50 +00:00
SysPanic ( ) ;
2022-04-13 14:43:38 +00:00
return false ;
}
else if ( pid > 0 )
{
2023-09-23 07:15:50 +00:00
if ( pipeStdOut_ [ 1 ] & &
pipeStdOut_ [ 1 ] ! = - 1 )
2022-04-05 10:11:19 +00:00
{
2022-04-13 14:43:38 +00:00
: : close ( AuExchange ( pipeStdOut_ [ 1 ] , 0 ) ) ;
}
2023-09-23 07:15:50 +00:00
if ( pipeStdErr_ [ 1 ] & &
pipeStdErr_ [ 1 ] ! = - 1 )
2022-04-13 14:43:38 +00:00
{
: : close ( AuExchange ( pipeStdErr_ [ 1 ] , 0 ) ) ;
2022-04-05 10:11:19 +00:00
}
2023-09-23 07:15:50 +00:00
if ( pipeStdIn_ [ 0 ] & &
pipeStdIn_ [ 0 ] ! = - 1 )
2022-04-13 14:43:38 +00:00
{
: : close ( AuExchange ( pipeStdIn_ [ 0 ] , 0 ) ) ;
}
this - > pidt_ = pid ;
2022-04-05 10:11:19 +00:00
this - > alive_ = true ;
2022-04-13 14:43:38 +00:00
{
2022-06-23 12:25:20 +00:00
AU_LOCK_GUARD ( gRWLock - > AsWritable ( ) ) ;
2022-04-13 14:43:38 +00:00
SysAssert ( AuTryInsert ( gPidLookupMap , pid , this ) ) ;
}
2022-04-05 10:11:19 +00:00
2022-04-13 14:43:38 +00:00
return true ;
2022-04-05 10:11:19 +00:00
}
else
{
2022-04-13 14:43:38 +00:00
return false ;
2022-04-05 10:11:19 +00:00
}
}
return true ;
}
2023-08-21 16:48:42 +00:00
AUKN_SYM IProcess * SpawnNew ( StartupParameters & & params )
2022-04-05 10:11:19 +00:00
{
2023-08-21 16:48:42 +00:00
auto ret = _new ProcessImpl ( AuMove ( params ) ) ;
2022-04-05 10:11:19 +00:00
if ( ! ret )
{
2022-04-13 14:43:38 +00:00
SysPushErrorMem ( ) ;
2022-04-05 10:11:19 +00:00
return { } ;
}
if ( ! ret - > Init ( ) )
{
2022-04-13 14:43:38 +00:00
SysPushErrorNested ( ) ;
2022-04-05 10:11:19 +00:00
delete ret ;
return { } ;
}
return ret ;
}
AUKN_SYM void SpawnRelease ( IProcess * process )
{
AuSafeDelete < ProcessImpl * > ( process ) ;
}
static void HandleChildTermiantion ( pid_t pid , int code )
{
2022-04-05 10:24:48 +00:00
AU_LOCK_GUARD ( gRWLock - > AsReadable ( ) ) ;
2022-04-05 10:11:19 +00:00
auto handler = gPidLookupMap . find ( pid ) ;
2022-04-13 14:43:38 +00:00
if ( handler = = gPidLookupMap . end ( ) )
{
return ;
}
2022-04-05 10:11:19 +00:00
{
auto process = * handler ;
process . second - > ByeLol ( code ) ;
}
}
static void SigChldHandler ( int )
{
int code ;
pid_t pid ;
while ( true )
{
pid = wait3 ( & code , WNOHANG , nullptr ) ;
if ( ( pid = = 0 ) | |
( pid = = - 1 ) )
{
break ;
}
HandleChildTermiantion ( pid , code ) ;
}
}
void InitUnix ( )
{
2022-04-05 10:24:48 +00:00
gRWLock = AuThreadPrimitives : : RWLockUnique ( ) ;
2022-04-06 01:24:38 +00:00
struct sigaction action =
{
. sa_handler = SigChldHandler ,
. sa_flags = SA_ONSTACK
} ;
2022-05-04 15:34:02 +00:00
: : sigemptyset ( & action . sa_mask ) ;
: : sigaction ( SIGCHLD , & action , nullptr ) ;
2022-04-05 10:11:19 +00:00
}
void DeinitUnix ( )
{
2022-04-06 01:24:38 +00:00
struct sigaction action =
{
. sa_handler = SIG_DFL ,
. sa_flags = SA_ONSTACK | SA_NOCLDWAIT
} ;
2022-05-04 15:34:02 +00:00
: : sigemptyset ( & action . sa_mask ) ;
: : sigaction ( SIGCHLD , & action , nullptr ) ;
2022-04-06 01:24:38 +00:00
2022-04-05 10:24:48 +00:00
gRWLock . reset ( ) ;
2022-04-05 10:11:19 +00:00
}
2022-04-05 10:24:48 +00:00
}