1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Process attach improvements

This commit is contained in:
Brian Fiete 2023-01-13 07:00:11 -05:00
parent 5146a92f2e
commit 2746a53839
5 changed files with 67 additions and 52 deletions

View file

@ -82,7 +82,7 @@ namespace System.Diagnostics
return .Ok;
}
public Result<void> AttachStandardInput(FileStream stream)
public Result<void> AttachStandardInput(IFileStream stream)
{
if (mSpawn == null)
return .Err;
@ -94,7 +94,7 @@ namespace System.Diagnostics
return .Ok;
}
public Result<void> AttachStandardOutput(FileStream stream)
public Result<void> AttachStandardOutput(IFileStream stream)
{
if (mSpawn == null)
return .Err;
@ -106,7 +106,7 @@ namespace System.Diagnostics
return .Ok;
}
public Result<void> AttachStandardError(FileStream stream)
public Result<void> AttachStandardError(IFileStream stream)
{
if (mSpawn == null)
return .Err;

View file

@ -6,7 +6,7 @@ using System;
namespace System.IO
{
public enum FileMode
public enum FileMode : int32
{
/// Creates a new file. Fails if the file already exists.
CreateNew = 1,

View file

@ -13,7 +13,7 @@ namespace System.IO
// Note these values currently match the values for FILE_SHARE_READ,
// FILE_SHARE_WRITE, and FILE_SHARE_DELETE in winnt.h
//
public enum FileShare
public enum FileShare : int32
{
/// No sharing. Any request to open the file (by this process or another
/// process) will fail until the file is closed.

View file

@ -109,7 +109,12 @@ namespace System.IO
}
}
class UnbufferedFileStream : FileStreamBase
interface IFileStream
{
Result<void> Attach(Platform.BfpFile* bfpFile, FileAccess access = .ReadWrite);
}
class UnbufferedFileStream : FileStreamBase, IFileStream
{
FileAccess mFileAccess;
@ -230,11 +235,12 @@ namespace System.IO
return .Ok;
}
public void Attach(Platform.BfpFile* bfpFile, FileAccess access = .ReadWrite)
public Result<void> Attach(Platform.BfpFile* bfpFile, FileAccess access = .ReadWrite)
{
Close();
mBfpFile = bfpFile;
mFileAccess = access;
return .Ok;
}
public override Result<void> Close()
@ -272,7 +278,7 @@ namespace System.IO
}
}
class BufferedFileStream : BufferedStream
class BufferedFileStream : BufferedStream, IFileStream
{
protected Platform.BfpFile* mBfpFile;
protected int64 mBfpFilePos;
@ -426,11 +432,12 @@ namespace System.IO
return .Ok;
}
public void Attach(Platform.BfpFile* bfpFile, FileAccess access = .ReadWrite)
public Result<void> Attach(Platform.BfpFile* bfpFile, FileAccess access = .ReadWrite)
{
Close();
mBfpFile = bfpFile;
mFileAccess = access;
return .Ok;
}
public override Result<void> Seek(int64 pos, SeekKind seekKind = .Absolute)
@ -559,6 +566,14 @@ namespace System.IO
return .Ok;
}
public override Result<void> Flush()
{
var result = base.Flush();
if (mBfpFile != null)
Platform.BfpFile_Flush(mBfpFile);
return result;
}
}
class FileStream : BufferedFileStream

View file

@ -334,7 +334,7 @@ uint64 Beefy::BFGetTickCountMicroFast()
uint32 outEndMS = timeGetTime();
uint64 endMicroA = __rdtsc();
// It's possible we can run this test in multiple threads at once, we could wrap a CritSect around it but
// It's possible we can run this test in multiple threads at once, we could wrap a CritSect around it but
// at least this fence will avoid the case where we have a zero gTimerDivisor
BF_FULL_MEMORY_FENCE();
gTimerInitialized = true;
@ -802,7 +802,7 @@ public:
return;
} */
//QueueRemove(fileWatcher);
//QueueRemove(fileWatcher);
//OutputDebugStrF("IOCP.Remove %@\n", fileWatcher);
@ -1195,7 +1195,7 @@ BFP_EXPORT BfpFileWatcher* BFP_CALLTYPE BfpFileWatcher_WatchDirectory(const char
UTF8Decode(path).c_str(), // Directory name
FILE_LIST_DIRECTORY, // access (read-write) mode
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, // security descriptor
NULL, // security descriptor
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // file attributes
NULL // file with attributes to copy
@ -1224,7 +1224,7 @@ BFP_EXPORT void BFP_CALLTYPE BfpFileWatcher_Release(BfpFileWatcher* fileWatcher)
{
IOCPManager::Get()->Remove(fileWatcher);
//::CloseHandle(fileWatcher->mFileHandle);
//fileWatcher->mFileHandle = NULL;
//fileWatcher->mFileHandle = NULL;
//delete fileWatcher;
}
@ -1524,10 +1524,10 @@ public:
return true;
}
// Using synchronous Anonymous pipes for process input/output redirection means we would end up
// wasting a worker threadpool thread per pipe instance. Overlapped pipe IO is desirable, since
// it will take advantage of the NT IO completion port infrastructure. But we can't really use
// Overlapped I/O for process input/output as it would break Console apps (managed Console class
// Using synchronous Anonymous pipes for process input/output redirection means we would end up
// wasting a worker threadpool thread per pipe instance. Overlapped pipe IO is desirable, since
// it will take advantage of the NT IO completion port infrastructure. But we can't really use
// Overlapped I/O for process input/output as it would break Console apps (managed Console class
// methods such as WriteLine as well as native CRT functions like printf) which are making an
// assumption that the console standard handles (obtained via GetStdHandle()) are opened
// for synchronous I/O and hence they can work fine with ReadFile/WriteFile synchrnously!
@ -1544,11 +1544,11 @@ public:
HANDLE dupHandle = 0;
// Duplicate the parent handle to be non-inheritable so that the child process
// Duplicate the parent handle to be non-inheritable so that the child process
// doesn't have access. This is done for correctness sake, exact reason is unclear.
// One potential theory is that child process can do something brain dead like
// One potential theory is that child process can do something brain dead like
// closing the parent end of the pipe and there by getting into a blocking situation
// as parent will not be draining the pipe at the other end anymore.
// as parent will not be draining the pipe at the other end anymore.
if (!::DuplicateHandle(GetCurrentProcess(), hTmp,
GetCurrentProcess(), &dupHandle,
0, false, DUPLICATE_SAME_ACCESS))
@ -1642,7 +1642,7 @@ public:
if ((flags & BfpSpawnFlag_NoWindow) != 0)
creationFlags |= CREATE_NO_WINDOW;
// set up the environment block parameter
// set up the environment block parameter
WCHAR* targetStrPtr = NULL;
UTF16String targetStrW;
@ -1904,12 +1904,12 @@ BFP_EXPORT void BFP_CALLTYPE BfpSpawn_Release(BfpSpawn* spawn)
// {
// DWORD dwID;
// GetWindowThreadProcessId(hwnd, &dwID);
//
//
// if (dwID == (DWORD)lParam)
// {
// PostMessage(hwnd, WM_CLOSE, 0, 0);
// }
//
//
// return TRUE;
// }
@ -2006,7 +2006,7 @@ BFP_EXPORT void BFP_CALLTYPE BfpSpawn_Kill(BfpSpawn* spawn, int exitCode, BfpKil
// ::SetConsoleCtrlHandler(NULL, true);
// ::GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
// //::Sleep(2000);
// ::FreeConsole();
// ::FreeConsole();
// ::SetConsoleCtrlHandler(NULL, false);
// if (!::TerminateProcess(spawn->mHProcess, (UINT)exitCode))
@ -2210,8 +2210,8 @@ BFP_EXPORT void BFP_CALLTYPE BfpThread_Resume(BfpThread* thread, BfpThreadResult
// The value for CONTEXT_XSTATE has changed between Windows 7 and
// Windows 7 SP1 and greater.
// While the value will be correct for future SDK headers, we need to set
// this value manually when building with a Windows 7 SDK for running on
// While the value will be correct for future SDK headers, we need to set
// this value manually when building with a Windows 7 SDK for running on
// Windows 7 SPI OS bits.
#undef CONTEXT_XSTATE
@ -2222,9 +2222,9 @@ BFP_EXPORT void BFP_CALLTYPE BfpThread_Resume(BfpThread* thread, BfpThreadResult
#define CONTEXT_XSTATE (0x00010040)
#endif
// Since the AVX API is not declared in the Windows 7 SDK headers and
// since we don't have the proper libs to work with, we will declare
// the API as function pointers and get them with GetProcAddress calls
// Since the AVX API is not declared in the Windows 7 SDK headers and
// since we don't have the proper libs to work with, we will declare
// the API as function pointers and get them with GetProcAddress calls
// from kernel32.dll. We also need to set some #defines.
#define XSTATE_AVX (XSTATE_GSSE)
@ -2251,20 +2251,20 @@ static CONTEXT* CaptureRegistersEx(HANDLE hThread, intptr*& curPtr)
PCONTEXT Context;
DWORD ContextSize;
DWORD64 FeatureMask;
DWORD FeatureLength;
DWORD FeatureLength;
BOOL Success;
PM128A Xmm;
PM128A Ymm;
if (pfnGetEnabledXStateFeatures == (PGETENABLEDXSTATEFEATURES)-1)
if (pfnGetEnabledXStateFeatures == (PGETENABLEDXSTATEFEATURES)-1)
return NULL;
if (pfnGetEnabledXStateFeatures == NULL)
{
HMODULE hm = GetModuleHandleA("kernel32.dll");
if (hm == NULL)
{
pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)-1;
pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)-1;
return NULL;
}
@ -2280,14 +2280,14 @@ static CONTEXT* CaptureRegistersEx(HANDLE hThread, intptr*& curPtr)
|| pfnLocateXStateFeature == NULL
|| pfnSetXStateFeaturesMask == NULL)
{
pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)-1;
pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)-1;
return NULL;
}
}
FeatureMask = pfnGetEnabledXStateFeatures();
if ((FeatureMask & XSTATE_MASK_AVX) == 0)
return NULL;
if ((FeatureMask & XSTATE_MASK_AVX) == 0)
return NULL;
ContextSize = 0;
Success = pfnInitializeContext(NULL,
@ -2303,23 +2303,23 @@ static CONTEXT* CaptureRegistersEx(HANDLE hThread, intptr*& curPtr)
&Context,
&ContextSize);
if (Success == FALSE)
return NULL;
if (Success == FALSE)
return NULL;
Success = pfnSetXStateFeaturesMask(Context, XSTATE_MASK_AVX);
if (Success == FALSE)
return Context;
if (Success == FALSE)
return Context;
Success = GetThreadContext(hThread, Context);
if (Success == FALSE)
return Context;
Success = GetThreadContext(hThread, Context);
if (Success == FALSE)
return Context;
Success = pfnGetXStateFeaturesMask(Context, &FeatureMask);
if (Success == FALSE)
return Context;
return Context;
if ((FeatureMask & XSTATE_MASK_AVX) == 0)
return Context;
if ((FeatureMask & XSTATE_MASK_AVX) == 0)
return Context;
Xmm = (PM128A)pfnLocateXStateFeature(Context, XSTATE_LEGACY_SSE, &FeatureLength);
Ymm = (PM128A)pfnLocateXStateFeature(Context, XSTATE_AVX, NULL);
@ -2375,7 +2375,7 @@ BFP_EXPORT void BFP_CALLTYPE BfpThread_GetIntRegisters(BfpThread* thread, intptr
if (outIntRegs == NULL)
return;
#ifdef BF32
#ifdef BF32
* (curPtr++) = (intptr)ctxPtr->Eax;
*(curPtr++) = (intptr)ctxPtr->Ebx;
*(curPtr++) = (intptr)ctxPtr->Ecx;
@ -2383,7 +2383,7 @@ BFP_EXPORT void BFP_CALLTYPE BfpThread_GetIntRegisters(BfpThread* thread, intptr
*(curPtr++) = (intptr)ctxPtr->Esi;
*(curPtr++) = (intptr)ctxPtr->Edi;
*(curPtr++) = (intptr)ctxPtr->Ebp;
#else
#else
* (curPtr++) = (intptr)ctxPtr->SegFs; // Testing
*(curPtr++) = (intptr)ctxPtr->Rax;
*(curPtr++) = (intptr)ctxPtr->Rbx;
@ -2401,7 +2401,7 @@ BFP_EXPORT void BFP_CALLTYPE BfpThread_GetIntRegisters(BfpThread* thread, intptr
*(curPtr++) = (intptr)ctxPtr->R14;
*(curPtr++) = (intptr)ctxPtr->R15;
memcpy(curPtr, &ctxPtr->Xmm0, 16 * 16);
curPtr += (16 * 16) / sizeof(intptr);
curPtr += (16 * 16) / sizeof(intptr);
#endif
* inOutIntRegCount = (int)(curPtr - outIntRegs);
@ -2595,7 +2595,7 @@ BFP_EXPORT bool BFP_CALLTYPE BfpEvent_WaitFor(BfpEvent* event, int waitMS)
{
if (GetLastError() == ERROR_TIMEOUT)
{
// Timeout
// Timeout
LeaveCriticalSection(&event->mCritSect);
return false;
}
@ -3522,7 +3522,7 @@ BFP_EXPORT BfpFindFileData* BFP_CALLTYPE BfpFindFileData_FindFirstFile(const cha
{
Beefy::String findStr = path;
Beefy::String wildcard;
int lastSlashPos = std::max((int)findStr.LastIndexOf('/'), (int)findStr.LastIndexOf('\\'));
if (lastSlashPos != -1)
{