Finish process

This commit is contained in:
2025-01-12 19:33:43 -06:00
parent 62c1aa6d3b
commit 01a034a77b
6 changed files with 195 additions and 28 deletions

View File

@ -4,13 +4,13 @@
#undef CROSSLANG_ENABLE_PROCESS
#endif
//#if defined(CROSSLANG_ENABLE_PROCESS)
#if defined(CROSSLANG_ENABLE_PROCESS)
#include "subprocess.h"
//#endif
#endif
namespace Tesses::CrossLang
{
//#if defined(CROSSLANG_ENABLE_PROCESS)
#if defined(CROSSLANG_ENABLE_PROCESS)
static TObject Process_Start(GCList& ls, std::vector<TObject> args)
{
@ -30,14 +30,22 @@ namespace Tesses::CrossLang
auto fobj = dict->GetValue("FileName");
auto myargs = dict->GetValue("Arguments");
auto env = dict->GetValue("Environment");
auto opt = dict->GetValue("Options");
//for any C# version
//RedirectStandardIn
//RedirectStandardOut
//RedirectStandardError
std::string filename;
TList* _args;
TList* env;
TList* env0;
std::vector<std::string> _args2;
std::vector<std::string> _env;
int64_t options;
if(GetObject(fobj,filename))
bool hasEnv=false;
if(!GetObject(fobj,filename))
{
gc->BarrierEnd();
return nullptr;
@ -54,24 +62,114 @@ namespace Tesses::CrossLang
}
}
}
if(GetObjectHeap(myargs,_args))
if(GetObjectHeap(env,env0))
{
for(auto a : _args->items)
hasEnv=true;
for(auto a : env0->items)
{
std::string a2;
if(GetObject(a,a2))
{
_args2.push_back(a2);
_env.push_back(a2);
}
}
}
const char** args3 = new const char*[sizeof(char*) * (_args2.size()+1)];
const char** env3 = hasEnv ? new const char*[sizeof(char*) * (_env.size()+1)] : nullptr;
for(size_t i = 0; i < _args2.size();i++)
args3[i] = _args2[i].c_str();
args3[_args2.size()]=NULL;
if(hasEnv)
{
for(size_t i = 0; i < _env.size();i++)
env3[i] = _env[i].c_str();
env3[_env.size()]=NULL;
}
if(!GetObject(opt,options))options=hasEnv ? 0 : subprocess_option_inherit_environment;
gc->BarrierEnd();
subprocess_create_ex()
struct subprocess_s* subprocess=new struct subprocess_s();
int r = subprocess_create_ex(args3,(int)options,env3,subprocess);
if(r != 0)
{
printf("Here2 %i\n",r);
delete[] args3;
delete[] env3;
delete subprocess;
return nullptr;
}
else
{
delete[] args3;
delete[] env3;
TDictionary* dict=TDictionary::Create(ls);
auto r = TNative::Create(ls,subprocess,[](void* v)->void{
delete (struct subprocess_s*)v;
});
gc->BarrierBegin();
dict->SetValue("_native",r);
gc->BarrierEnd();
dict->DeclareFunction(gc,"getHasExited","Gets whether process has stopped",{},[r](GCList& ls, std::vector<TObject> args)->TObject{
if(r->GetDestroyed()) return true;
return subprocess_alive((struct subprocess_s*)r->GetPointer()) == 0;
});
dict->DeclareFunction(gc,"Join","Wait till process exits and get its return code",{},[r](GCList& ls, std::vector<TObject> args)->TObject{
if(r->GetDestroyed()) return nullptr;
int returnCode;
if(subprocess_join((struct subprocess_s*)r->GetPointer(),&returnCode) == 0)
{
return (int64_t)returnCode;
}
return nullptr;
});
dict->DeclareFunction(gc,"Terminate","Terminate the process",{},[r](GCList& ls, std::vector<TObject> args)->TObject{
if(r->GetDestroyed()) return nullptr;
subprocess_terminate((struct subprocess_s*)r->GetPointer());
return nullptr;
});
dict->DeclareFunction(gc,"Close","Wait till process exits and get its return code",{},[r](GCList& ls, std::vector<TObject> args)->TObject{
if(r->GetDestroyed()) return nullptr;
r->Destroy();
return nullptr;
});
dict->DeclareFunction(gc,"getStandardInput","Gets the standard input stream",{},[r](GCList& ls,std::vector<TObject> args)->TObject {
if(r->GetDestroyed()) return nullptr;
return TStreamHeapObject::Create(ls,new Tesses::Framework::Streams::FileStream(subprocess_stdin((struct subprocess_s*)r->GetPointer()),false,"w",false));
});
dict->DeclareFunction(gc,"getStandardOutput","Gets the standard output stream",{},[r](GCList& ls,std::vector<TObject> args)->TObject {
if(r->GetDestroyed()) return nullptr;
return TStreamHeapObject::Create(ls,new Tesses::Framework::Streams::FileStream(subprocess_stdout((struct subprocess_s*)r->GetPointer()),false,"r",false));
});
dict->DeclareFunction(gc,"getStandardError","Gets the standard error stream",{},[r](GCList& ls,std::vector<TObject> args)->TObject {
if(r->GetDestroyed()) return nullptr;
return TStreamHeapObject::Create(ls,new Tesses::Framework::Streams::FileStream(subprocess_stderr((struct subprocess_s*)r->GetPointer()),false,"r",false));
});
return dict;
}
}
return nullptr;
}
//#endif
#endif
void TStd::RegisterProcess(GC* gc,TRootEnvironment* env)
{
env->permissions.canRegisterProcess=true;
GCList ls(gc);
TDictionary* dict = TDictionary::Create(ls);
#if defined(CROSSLANG_ENABLE_PROCESS)
dict->DeclareFunction(gc,"Start","Start a process",{"process_object"},Process_Start);
#endif
gc->BarrierBegin();
env->SetVariable("Process",dict);
gc->BarrierEnd();
}
}

View File

@ -188,6 +188,7 @@ namespace Tesses::CrossLang
this->canRegisterNet=false;
this->canRegisterOGC=false;
this->canRegisterPath=false;
this->canRegisterProcess=false;
this->canRegisterRoot=false;
this->canRegisterSDL2=false;
this->canRegisterSqlite=false;
@ -224,6 +225,7 @@ namespace Tesses::CrossLang
}
void TStd::RegisterStd(GC* gc, TRootEnvironment* env)
{
env->permissions.canRegisterEverything=true;
RegisterEnv(gc, env);
RegisterRoot(gc,env);
RegisterPath(gc,env);
@ -237,6 +239,16 @@ namespace Tesses::CrossLang
RegisterCrypto(gc,env);
RegisterSDL2(gc, env);
RegisterOGC(gc, env);
RegisterProcess(gc,env);
gc->RegisterEverything(env);
GCList ls(gc);
TDictionary* dict = TDictionary::Create(ls);
gc->BarrierBegin();
env->SetVariable("Reflection",dict);
gc->BarrierEnd();
env->permissions.locked=true;
}
}

View File

@ -226,6 +226,16 @@ namespace Tesses::CrossLang
for(auto item : objects) delete item;
delete this->mtx;
}
void GC::RegisterEverythingCallback(std::function<void(GC* gc, TRootEnvironment* env)> cb)
{
this->register_everything.push_back(cb);
}
void GC::RegisterEverything(TRootEnvironment* env)
{
for(auto item : this->register_everything)
item(this,env);
}
void GC::Collect()
{
this->BarrierBegin();

View File

@ -1772,6 +1772,7 @@ namespace Tesses::CrossLang {
auto vfs = dynamic_cast<TVFSHeapObject*>(obj);
auto env = dynamic_cast<TEnvironment*>(obj);
auto rootEnv = dynamic_cast<TRootEnvironment*>(obj);
auto callable = dynamic_cast<TCallable*>(obj);
if(rootEnv != nullptr)
{
@ -1784,12 +1785,17 @@ namespace Tesses::CrossLang {
//TStd::RegisterOGC
//TStd::RegisterPath
//TStd::RegisterRoot
//TStd::RegisterSDL2
//TStd::RegisterSqlite
//TStd::RegisterVM
auto myEnv = cse.back()->env->GetRootEnvironment();
if(key == "RegisterEverything")
{
if(myEnv->permissions.canRegisterEverything)
{
TStd::RegisterStd(gc, rootEnv);
}
else
{
if(myEnv->permissions.canRegisterConsole && !rootEnv->permissions.locked)
TStd::RegisterConsole(gc, rootEnv);
@ -1829,34 +1835,44 @@ namespace Tesses::CrossLang {
if(myEnv->permissions.canRegisterVM && !rootEnv->permissions.locked)
TStd::RegisterVM(gc, rootEnv);
if(myEnv->permissions.canRegisterProcess && !rootEnv->permissions.locked)
TStd::RegisterProcess(gc, rootEnv);
}
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterConsole")
{
if(myEnv->permissions.canRegisterConsole && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterConsole) && !rootEnv->permissions.locked)
TStd::RegisterConsole(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterProcess")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterProcess) && !rootEnv->permissions.locked)
TStd::RegisterProcess(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterCrypto")
{
if(myEnv->permissions.canRegisterCrypto && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterCrypto) && !rootEnv->permissions.locked)
TStd::RegisterCrypto(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterDictionary")
{
if(myEnv->permissions.canRegisterDictionary && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterDictionary) && !rootEnv->permissions.locked)
TStd::RegisterDictionary(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterEnv")
{
if(myEnv->permissions.canRegisterEnv && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterEnv) && !rootEnv->permissions.locked)
TStd::RegisterDictionary(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
@ -1866,7 +1882,7 @@ namespace Tesses::CrossLang {
bool r;
if(GetArgument(args,0,r))
{
if(myEnv->permissions.canRegisterIO && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterIO) && !rootEnv->permissions.locked)
TStd::RegisterIO(gc, rootEnv, myEnv->permissions.canRegisterLocalFS ? r : false);
}
cse.back()->Push(gc,nullptr);
@ -1875,35 +1891,35 @@ namespace Tesses::CrossLang {
}
if(key == "RegisterJson")
{
if(myEnv->permissions.canRegisterJSON && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterJSON) && !rootEnv->permissions.locked)
TStd::RegisterJson(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterNet")
{
if(myEnv->permissions.canRegisterNet && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterNet) && !rootEnv->permissions.locked)
TStd::RegisterNet(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterOGC")
{
if(myEnv->permissions.canRegisterOGC && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterOGC) && !rootEnv->permissions.locked)
TStd::RegisterOGC(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterPath")
{
if(myEnv->permissions.canRegisterPath && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterPath) && !rootEnv->permissions.locked)
TStd::RegisterPath(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterRoot")
{
if(myEnv->permissions.canRegisterRoot && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterRoot) && !rootEnv->permissions.locked)
TStd::RegisterRoot(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
@ -1911,14 +1927,14 @@ namespace Tesses::CrossLang {
if(key == "RegisterSDL2")
{
if(myEnv->permissions.canRegisterSDL2 && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterSDL2) && !rootEnv->permissions.locked)
TStd::RegisterSDL2(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterSqlite")
{
if(myEnv->permissions.canRegisterSqlite && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterSqlite) && !rootEnv->permissions.locked)
TStd::RegisterSqlite(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
@ -1958,7 +1974,7 @@ namespace Tesses::CrossLang {
}
if(key == "RegisterVM")
{
if(myEnv->permissions.canRegisterVM && !rootEnv->permissions.locked)
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterVM) && !rootEnv->permissions.locked)
TStd::RegisterVM(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
@ -3040,6 +3056,29 @@ namespace Tesses::CrossLang {
return InvokeMethod(ls,o,dict,args);
}
else if(callable != nullptr)
{
if(key == "Call")
{
TList* argls;
if(GetArgumentHeap(args,0,argls))
{
TClosure* clo = dynamic_cast<TClosure*>(callable);
if(clo != nullptr)
{
AddCallStackEntry(ls,clo,argls->items);
return true;
}
else
{
cse.back()->Push(gc,callable->Call(ls, argls->items));
return false;
}
}
}
cse.back()->Push(gc,nullptr);
return false;
}
else
{
cse.back()->Push(gc, Undefined());