1#ifndef FSTEXTERNBRIDGE_H
2#define FSTEXTERNBRIDGE_H
65 #ifndef WIN32_LEAN_AND_MEAN
66 #define WIN32_LEAN_AND_MEAN
149 static bool notice_fired=
false;
152 std::ostringstream sos; sos <<
"NOTE: --extern-cmd executes user-supplied code through the system shell: " <<
_cmd << std::endl;
158 SECURITY_ATTRIBUTES sa; sa.nLength=
sizeof(sa); sa.bInheritHandle=TRUE; sa.lpSecurityDescriptor=NULL;
159 HANDLE in_rd=0,in_wr=0,out_rd=0,out_wr=0;
160 if(!CreatePipe(&in_rd,&in_wr,&sa,0) || !CreatePipe(&out_rd,&out_wr,&sa,0))
162 SetHandleInformation(in_wr,HANDLE_FLAG_INHERIT,0);
163 SetHandleInformation(out_rd,HANDLE_FLAG_INHERIT,0);
164 STARTUPINFOA si; ZeroMemory(&si,
sizeof(si)); si.cb=
sizeof(si);
165 si.dwFlags=STARTF_USESTDHANDLES;
166 si.hStdInput=in_rd; si.hStdOutput=out_wr; si.hStdError=GetStdHandle(STD_ERROR_HANDLE);
167 PROCESS_INFORMATION pi; ZeroMemory(&pi,
sizeof(pi));
168 std::string full=std::string(
"cmd.exe /C ")+
_cmd;
169 std::vector<char> cmdbuf(full.begin(),full.end()); cmdbuf.push_back(
'\0');
170 if(!CreateProcessA(NULL,cmdbuf.data(),NULL,NULL,TRUE,0,NULL,NULL,&si,&pi))
171 {CloseHandle(in_rd);CloseHandle(in_wr);CloseHandle(out_rd);CloseHandle(out_wr);
173 CloseHandle(pi.hThread);
174 CloseHandle(in_rd); CloseHandle(out_wr);
175 _child_process=pi.hProcess;
176 _to_child=_fdopen(_open_osfhandle((intptr_t)in_wr,_O_WRONLY|_O_BINARY),
"wb");
177 _from_child=_fdopen(_open_osfhandle((intptr_t)out_rd,_O_RDONLY|_O_BINARY),
"rb");
181 int to_pipe[2], from_pipe[2];
183 fcntl(to_pipe[1],F_SETFD,FD_CLOEXEC);
184 fcntl(from_pipe[0],F_SETFD,FD_CLOEXEC);
190 fcntl(to_pipe[1],F_SETNOSIGPIPE,1);
195 signal(SIGPIPE,SIG_IGN);
197 const pid_t pid=fork();
200 dup2(to_pipe[0],0); dup2(from_pipe[1],1);
201 close(to_pipe[0]); close(to_pipe[1]); close(from_pipe[0]); close(from_pipe[1]);
202 execl(
"/bin/sh",
"sh",
"-c",
_cmd.c_str(),(
char*)0);
205 close(to_pipe[0]); close(from_pipe[1]);
227 if(_child_process) {WaitForSingleObject(_child_process,2000); TerminateProcess(_child_process,0); CloseHandle(_child_process); _child_process=0;}
260 if(!out.empty() && out.back()==
'\n') {out.pop_back();
if(!out.empty() && out.back()==
'\r') out.pop_back();
return out;}
261 if(out.size()>1048576)
272 HANDLE _child_process;
Persistent-child-process line-protocol plumbing shared by the external-tool bridges: Classifier_Exter...
Definition extern_bridge.hpp:105
pid_t _child_pid
POSIX pid of the running child, or -1 when not running().
Definition extern_bridge.hpp:274
void die_on_write() const
shared loud-failure path for owner-side writes
Definition extern_bridge.hpp:117
std::FILE * _to_child
write end of the pipe to the child's stdin, or nullptr when not running()
Definition extern_bridge.hpp:269
void send_line(const std::string &line)
Writes line followed by a newline to the child's stdin. Requires running(). Throws (via die_on_write(...
Definition extern_bridge.hpp:237
void init_process_handles()
Resets the handles/pid to their "not running" sentinel values (nullptr / -1). Called from the constru...
Definition extern_bridge.hpp:279
void ensure_process()
Lazily spawns the child process if not already running() (a no-op otherwise). Requires get_command() ...
Definition extern_bridge.hpp:136
std::FILE * to_child()
for owner-side row streaming (%.17g formatting stays with the owner)
Definition extern_bridge.hpp:115
void set_command(const std::string &cmd)
sets the external command line; must be called before the child process is spawned (ensure_process())
Definition extern_bridge.hpp:112
Extern_Bridge(const char *component)
component names the owning component (e.g. "Classifier_Extern"), prefixing every diagnostic; does not...
Definition extern_bridge.hpp:107
void shutdown_process()
Terminates the child, if any, and returns the bridge to a not-running() state. Closing our end of std...
Definition extern_bridge.hpp:222
std::string _component
owning component name, prefixes every diagnostic
Definition extern_bridge.hpp:267
std::string _cmd
the configured external command line (see set_command())
Definition extern_bridge.hpp:268
const std::string & get_command() const
returns the configured command line
Definition extern_bridge.hpp:113
std::string read_line()
Reads one line from the child's stdout, with the trailing "\n" (and a preceding "\r",...
Definition extern_bridge.hpp:250
void flush_to_child()
flushes buffered writes to the child's stdin (call after a batch of send_line()/owner-side writes,...
Definition extern_bridge.hpp:116
std::FILE * _from_child
read end of the pipe from the child's stdout, or nullptr when not running()
Definition extern_bridge.hpp:270
bool running() const
true once ensure_process() has successfully spawned a child that has not since been shut down
Definition extern_bridge.hpp:114
FST4 specific error passing class.
Definition error.hpp:61
static void print(std::ostream &os, std::ostringstream &sos)
Writes sos's buffered content to os, serializing concurrent writers under FST_THREADED via a shared m...
Definition global.hpp:86
FST4 specific error passing class.
The Feature Selection Toolbox 4 library: every library component – data access, criteria and classifi...
Definition data_accessor.hpp:80
std::mutex & extern_spawn_mutex()
Definition extern_bridge.hpp:82