38# if !defined(WIN32_LEAN_AND_MEAN)
39# define WIN32_LEAN_AND_MEAN
49inline std::string lastError2String()
51 int error=GetLastError();
53 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
nullptr,
error, 0, buff, 1024,
nullptr);
55 return std::string(buff);
59#define READ_FROM_PIPE 0
60#define WRITE_TO_PIPE 1
61#define REDIRECT_TO(from, to) yarp::run::impl::dup2(to, from)
71std::string yarp::run::Run::mPortName;
73int yarp::run::Run::mProcCNT=0;
74bool yarp::run::Run::mStresstest=
false;
75bool yarp::run::Run::mLogged=
false;
76std::string yarp::run::Run::mLoggerPort(
"/yarplogger");
88 sprintf(msg,
"SIGNAL %d", sig);
104 const char *at = txt.c_str();
107 for (
char ch : txt) {
109 result.
addString(std::string(at, len-slash_tweak));
115 slash_tweak = (ch==
slash && len>0)?1:0;
119 result.
addString(std::string(at, len-slash_tweak));
127 fp = fopen(fname,
"r");
139 for (
const auto& s_iter : ss)
142 if (sss.size() == 2 && sss[0] ==
"YARP_LOG_PROCESS_LABEL")
151int yarp::run::Run::main(
int argc,
char *argv[])
157 if (config.
check(
"server"))
159 mLogged=config.
check(
"log");
165 if (botPortLogger.
size()>1)
171 mPortName=std::string(config.
find(
"server").
asString());
181 fprintf(stderr,
"ERROR: no yarp network found.\n");
188 if (config.
check(
"readwrite"))
191 std::string fPortName;
192 std::string lPortName;
194 if (config.
check(
"forward"))
204#elif defined(__APPLE__)
207 struct sigaction new_action;
209 sigfillset(&new_action.sa_mask);
210 new_action.sa_flags=0;
212 sigaction(SIGTERM, &new_action,
nullptr);
213 sigaction(SIGHUP, &new_action,
nullptr);
216 yarp::os::impl::signal(SIGPIPE, SIG_IGN);
218 if (getppid()==1)
return 0;
220 yarp::run::impl::prctl(PR_SET_PDEATHSIG, SIGTERM);
222 struct sigaction new_action;
224 yarp::os::impl::sigfillset(&new_action.sa_mask);
225 new_action.sa_flags=0;
227 yarp::os::impl::sigaction(SIGTERM, &new_action,
nullptr);
228 yarp::os::impl::signal(SIGHUP, SIG_IGN);
230 yarp::os::impl::signal(SIGPIPE, SIG_IGN);
246 if (config.
check(
"write"))
255 struct sigaction new_action;
257 yarp::os::impl::sigfillset(&new_action.sa_mask);
258 new_action.sa_flags=0;
259 yarp::os::impl::sigaction(SIGTERM, &new_action,
nullptr);
261 yarp::os::impl::signal(SIGPIPE, SIG_IGN);
262 yarp::os::impl::signal(SIGHUP, SIG_IGN);
265 if (config.
check(
"log"))
287 if (config.
check(
"read"))
298 yarp::os::impl::signal(SIGHUP, SIG_IGN);
310 if (config.
check(
"stresstest"))
312 fprintf(stderr,
"Yarprun stress test started.\n");
315 int max_interval_ms=config.
find(
"stresstest").
asInt32();
320 config.
unput(
"stresstest");
324 bool isCommand=
false;
326 if (config.
check(
"cmd"))
333 unsigned int t=0, u=0;
337 char cmd_and_name[512];
341 std::random_device rd;
342 std::mt19937 mt(rd());
343 std::uniform_int_distribution<int> dist0maxint(0, max_interval_ms -1);
351 sprintf(tag,
"%s_%u", tag_zero.c_str(), t++);
352 stresser.
put(
"as", tag);
356 sprintf(cmd_and_name,
"%s --name /%s", cmd.c_str(), tag);
357 stresser.
put(
"cmd", cmd_and_name);
362 std::uniform_int_distribution<int> dist07(0, 7);
363 if (isCommand && ++term_cycle>=4)
367 int r = t - (dist07(mt));
369 for (
int i=u; i<r; ++i)
371 sprintf(tag,
"%s_%u", tag_zero.c_str(), i);
392 if (config.
check(
"help"))
400 if (config.
check(
"stdio")
401 || config.
check(
"cmd")
402 || config.
check(
"kill")
403 || config.
check(
"sigterm")
404 || config.
check(
"sigtermall")
405 || config.
check(
"exit")
406 || config.
check(
"isrunning")
407 || config.
check(
"ps")
408 || config.
check(
"env")
409 || config.
check(
"sysinfo")
410 || config.
check(
"which"))
426 for (
int r=0; r<RETRY; ++r)
430 if (!port.
open(
"..."))
443 RUNLOG(
"<<<port.write(msg, response)")
444 if (!port.write(msg, response))
450 RUNLOG(
">>>port.write(msg, response)")
452 yarp::os::Network::disconnect(port.getName(), target);
455 fprintf(stderr, "RESPONSE:\n=========\n");
456 for (
size_t s=0; s<response.size(); ++s)
458 fprintf(stderr,
"%s\n", response.get(s).toString().c_str());
466 response.
addString(
"Cannot connect to remote server, aborting...\n");
467 for (
size_t s=0; s<response.
size(); ++s)
469 fprintf(stderr,
"%s\n", response.
get(s).
toString().c_str());
477 yarp::run::Run::mStresstest=
false;
479 if (yarp::run::Run::pServerPort)
482 yarp::run::Run::pServerPort =
nullptr;
493int yarp::run::Run::server()
499 if (!port.
open(mPortName.c_str()))
501 yError() <<
"Yarprun failed to open port: " << mPortName.c_str();
512 yInfo() <<
"Yarprun successfully started on port: " << mPortName.c_str();
526 RUNLOG(
"<<<port.read(msg, true)")
527 if (!port.read(msg, true)) break;
528 RUNLOG(">>>port.read(msg, true)")
530 if (!pServerPort) break;
538 if (msg.check("stdio"))
541 std::string strStdioPort=msg.find(
"stdio").asString();
543 if (strOnPort==mPortName)
549 msg.addList()=botUUID;
551 if (mLogged || msg.check(
"log"))
554 std::string portName=
"/log";
555 portName+=mPortName+
"/";
556 std::string command = msg.findGroup(
"cmd").get(1).asString();
557 command = command.substr(0, command.find(
' '));
558 command = command.substr(command.find_last_of(
"\\/") + 1);
564 if (msg.check(
"log"))
568 if (botLogger.
size()>1)
581 msg.addList()=botFwd;
585 if (executeCmdAndStdio(msg, cmdResult)>0)
587 if (strStdioPort==mPortName)
590 userStdio(msg, stdioResult);
591 cmdResult.
append(stdioResult);
595 cmdResult.
append(sendMsg(msg, strStdioPort));
599 port.
reply(cmdResult);
604 userStdio(msg, stdioResult);
605 port.
reply(stdioResult);
612 if (msg.check(
"cmd"))
616 if (msg.check(
"log"))
620 if (botLogger.
size()>1)
622 std::string loggerName=botLogger.
get(1).
asString();
623 executeCmdStdout(msg, cmdResult, loggerName);
627 executeCmdStdout(msg, cmdResult, mLoggerPort);
632 executeCmdStdout(msg, cmdResult, mLoggerPort);
636 executeCmd(msg, cmdResult);
638 port.
reply(cmdResult);
642 if (msg.check(
"kill"))
644 std::string alias(msg.findGroup(
"kill").get(1).asString());
645 int sig=msg.findGroup(
"kill").get(2).asInt32();
647 result.
addString(mProcessVector.Signal(alias, sig)?
"kill OK":
"kill FAILED");
652 if (msg.check(
"sigterm"))
654 std::string alias(msg.find(
"sigterm").asString());
656 result.
addString(mProcessVector.Signal(alias, SIGTERM)?
"sigterm OK":
"sigterm FAILED");
661 if (msg.check(
"sigtermall"))
663 mProcessVector.Killall(SIGTERM);
673 result.
append(mProcessVector.PS());
678 if (msg.check(
"isrunning"))
680 std::string alias(msg.find(
"isrunning").asString());
682 result.
addString(mProcessVector.IsRunning(alias)?
"running":
"not running");
687 if (msg.check(
"killstdio"))
689 std::string alias(msg.find(
"killstdio").asString());
690 mStdioVector.Signal(alias, SIGTERM);
699 if (msg.check(
"sysinfo"))
706 if (msg.check(
"which"))
708 std::string fileName=msg.find(
"which").asString();
712 for (
int i=0; i<possiblePaths.
size(); ++i)
714 std::string guessString=possiblePaths.
get(i).
asString() +
715 std::string{
slash} + fileName;
716 const char* guess=guessString.c_str();
719 fileName=
"\"" + std::string(guess) +
"\"";
725 port.
reply(fileNameWriter);
729 if (msg.check(
"exit"))
740 Run::mStdioVector.Killall(SIGTERM);
742 Run::mProcessVector.Killall(SIGTERM);
751void yarp::run::Run::cleanBeforeExec()
763 mProcessVector =
nullptr;
769 mStdioVector =
nullptr;
772 if (mBraveZombieHunter)
775 mBraveZombieHunter =
nullptr;
783void yarp::run::Run::writeToPipe(
int fd, std::string str)
785 int len = str.length() + 1;
788 if (
ret !=
sizeof(len)) {
789 fprintf(stderr,
"Warning: could not write string length to pipe.\n");
793 fprintf(stderr,
"Warning: could not write string to pipe.\n");
797int yarp::run::Run::readFromPipe(
int fd,
char* &data,
int& buffsize)
800 char* buff=(
char*)&len;
802 for (
int c=4, r=0; c>0; c-=r)
820 data=
new char[buffsize=1024+(len/1024)*1024];
825 for (
int c=len, r=0; c>0; c-=r)
842 if (yarp::run::Run::mBraveZombieHunter)
848int yarp::run::Run::server()
850 int pipe_server2manager[2];
851 int pipe_manager2server[2];
853 if (yarp::run::impl::pipe(pipe_server2manager))
855 fprintf(stderr,
"Can't open pipe because %s\n", strerror(errno));
861 if (yarp::run::impl::pipe(pipe_manager2server))
863 fprintf(stderr,
"Can't open pipe because %s\n", strerror(errno));
869 int pid_process_manager=yarp::run::impl::fork();
871 if (IS_INVALID(pid_process_manager))
880 fprintf(stderr,
"Can't fork process manager because %s\n", strerror(
error));
886 if (IS_PARENT_OF(pid_process_manager))
888 yarp::os::impl::signal(SIGPIPE, SIG_IGN);
895 if (!port.
open(mPortName))
897 yError() <<
"Yarprun failed to open port: " << mPortName.c_str();
899 if (mPortName[0] !=
'/') {
900 yError(
"Invalid port name '%s', it should start with '/'\n", mPortName.c_str());
912 yInfo() <<
"Yarprun successfully started on port: " << mPortName.c_str();
920 char *rsp_str=
new char[rsp_size];
926 RUNLOG(
"<<<port.read(msg, true)")
927 if (!port.read(msg, true)) {
930 RUNLOG(
">>>port.read(msg, true)")
936 if (msg.
check(
"sysinfo"))
943 if (msg.
check(
"which"))
949 for (
size_t i=0; i<possiblePaths.
size(); ++i)
952 const char* guess=guessString.c_str();
961 port.
reply(fileNameWriter);
965 if (msg.
check(
"exit"))
967 pServerPort =
nullptr;
980 int nread=readFromPipe(pipe_manager2server[
READ_FROM_PIPE], rsp_str, rsp_size);
985 fprintf(stderr,
"ERROR: broken pipe between server and manager\n");
993 port.
reply(response);
1007 if (IS_NEW_PROCESS(pid_process_manager))
1009 yarp::os::impl::signal(SIGPIPE, SIG_IGN);
1020 mBraveZombieHunter->
start();
1027 char *msg_str=
new char[msg_size];
1034 RUNLOG(
"<<<readFromPipe")
1035 if (readFromPipe(pipe_server2manager[
READ_FROM_PIPE], msg_str, msg_size) <= 0) {
1038 RUNLOG(
">>>readFromPipe")
1043 msg.fromString(msg_str);
1046 if (msg.check("stdio"))
1051 if (strOnPort==mPortName)
1059 if (mLogged || msg.
check(
"log"))
1062 std::string portName=
"/log";
1063 portName+=mPortName+
"/";
1065 command = command.substr(0, command.find(
' '));
1066 command = command.substr(command.find_last_of(
"\\/") + 1);
1072 if (msg.
check(
"log"))
1076 if (botLogger.
size()>1)
1097 if (executeCmdAndStdio(msg, cmdResult)>0)
1099 if (strStdioPort==mPortName)
1102 userStdio(msg, stdioResult);
1103 cmdResult.
append(stdioResult);
1107 cmdResult.
append(sendMsg(msg, strStdioPort));
1118 userStdio(msg, stdioResult);
1128 if (msg.check("cmd"))
1132 if (msg.
check(
"log"))
1136 if (botLogger.
size()>1)
1138 std::string loggerName=botLogger.
get(1).
asString();
1139 executeCmdStdout(msg, cmdResult, loggerName);
1143 executeCmdStdout(msg, cmdResult, mLoggerPort);
1148 executeCmdStdout(msg, cmdResult, mLoggerPort);
1152 executeCmd(msg, cmdResult);
1161 if (msg.check("kill"))
1166 result.
addString(mProcessVector->Signal(alias, sig)?
"kill OK":
"kill FAILED");
1173 if (msg.check("sigterm"))
1177 result.
addString(mProcessVector->Signal(alias, SIGTERM)?
"sigterm OK":
"sigterm FAILED");
1184 if (msg.check("sigtermall"))
1186 mProcessVector->Killall(SIGTERM);
1196 if (msg.check("ps"))
1199 result.
append(mProcessVector->PS());
1206 if (msg.check("isrunning"))
1210 result.
addString(mProcessVector->IsRunning(alias)?
"running":
"not running");
1217 if (msg.check("killstdio"))
1220 mStdioVector->Signal(alias, SIGTERM);
1230 mStdioVector->Killall(SIGTERM);
1232 mProcessVector->Killall(SIGTERM);
1234 if (mBraveZombieHunter)
1236 mBraveZombieHunter->stop();
1237 delete mBraveZombieHunter;
1238 mBraveZombieHunter =
nullptr;
1241 delete mProcessVector;
1243 delete mStdioVector;
1265 if (config.
check(
"cmd") && config.
check(
"stdio"))
1271 Help(
"SYNTAX ERROR: missing remote stdio server\n");
1276 Help(
"SYNTAX ERROR: missing command\n");
1281 Help(
"SYNTAX ERROR: missing tag\n");
1286 Help(
"SYNTAX ERROR: missing remote server\n");
1292 printf(
"*********** %s ************\n", config.
toString().c_str());
1300 if (config.
check(
"workdir")) {
1303 if (config.
check(
"geometry")) {
1306 if (config.
check(
"hold")) {
1309 if (config.
check(
"env")) {
1312 if (config.
check(
"log")) {
1328 if (!response.
size()) {
1341 if (config.
check(
"cmd"))
1347 Help(
"SYNTAX ERROR: missing command\n");
1352 Help(
"SYNTAX ERROR: missing tag\n");
1357 Help(
"SYNTAX ERROR: missing remote server\n");
1367 if (config.
check(
"workdir")) {
1370 if (config.
check(
"log")) {
1381 if (config.
check(
"env")) {
1387 if (!response.
size()) {
1403 if (config.
check(
"kill"))
1407 Help(
"SYNTAX ERROR: missing remote server\n");
1412 Help(
"SYNTAX ERROR: missing tag\n");
1417 Help(
"SYNTAX ERROR: missing signum\n");
1426 if (!response.
size())
1435 if (config.
check(
"sigterm"))
1439 Help(
"SYNTAX ERROR: missing tag");
1444 Help(
"SYNTAX ERROR: missing remote server\n");
1453 if (!response.
size())
1458 return response.
get(0).
asString()==
"sigterm OK"?0:2;
1462 if (config.
check(
"sigtermall"))
1466 Help(
"SYNTAX ERROR: missing remote server\n");
1475 if (!response.
size())
1483 if (config.
check(
"ps"))
1487 Help(
"SYNTAX ERROR: missing remote server\n");
1496 if (!response.
size())
1504 if (config.
check(
"isrunning"))
1508 Help(
"SYNTAX ERROR: missing remote server\n");
1514 Help(
"SYNTAX ERROR: missing tag\n");
1523 if (!response.
size())
1531 if (config.
check(
"sysinfo"))
1535 Help(
"SYNTAX ERROR: missing remote server\n");
1544 if (!port.
open(
"..."))
1546 fprintf(stderr,
"RESPONSE:\n=========\n");
1547 fprintf(stderr,
"Cannot open port, aborting...\n");
1556 fprintf(stderr,
"RESPONSE:\n=========\n");
1557 fprintf(stderr,
"Cannot connect to remote server, aborting...\n");
1565 RUNLOG(
"<<<port.write(msg, info)")
1567 RUNLOG(
">>>port.write(msg, info)")
1571 fprintf(stdout,
"RESPONSE:\n=========\n\n");
1575 fprintf(stdout,
"No response. (timeout)\n");
1580 fprintf(stdout,
"Platform name : %s\n",
info.platform.name.c_str());
1581 fprintf(stdout,
"Platform dist : %s\n",
info.platform.distribution.c_str());
1582 fprintf(stdout,
"Platform release : %s\n",
info.platform.release.c_str());
1583 fprintf(stdout,
"Platform code : %s\n",
info.platform.codename.c_str());
1584 fprintf(stdout,
"Platform kernel : %s\n\n",
info.platform.kernel.c_str());
1586 fprintf(stdout,
"User Id : %d\n",
info.user.userID);
1587 fprintf(stdout,
"User name : %s\n",
info.user.userName.c_str());
1588 fprintf(stdout,
"User real name : %s\n",
info.user.realName.c_str());
1589 fprintf(stdout,
"User home dir : %s\n\n",
info.user.homeDir.c_str());
1591 fprintf(stdout,
"Cpu load Ins.: %d\n",
info.load.cpuLoadInstant);
1592 fprintf(stdout,
"Cpu load 1 : %.2lf\n",
info.load.cpuLoad1);
1593 fprintf(stdout,
"Cpu load 5 : %.2lf\n",
info.load.cpuLoad5);
1594 fprintf(stdout,
"Cpu load 15 : %.2lf\n\n",
info.load.cpuLoad15);
1596 fprintf(stdout,
"Memory total : %dM\n",
info.memory.totalSpace);
1597 fprintf(stdout,
"Memory free : %dM\n\n",
info.memory.freeSpace);
1599 fprintf(stdout,
"Storage total : %dM\n",
info.storage.totalSpace);
1600 fprintf(stdout,
"Storage free : %dM\n\n",
info.storage.freeSpace);
1602 fprintf(stdout,
"Processor model : %s\n",
info.processor.model.c_str());
1603 fprintf(stdout,
"Processor model num : %d\n",
info.processor.modelNumber);
1604 fprintf(stdout,
"Processor family : %d\n",
info.processor.family);
1605 fprintf(stdout,
"Processor vendor : %s\n",
info.processor.vendor.c_str());
1606 fprintf(stdout,
"Processor arch : %s\n",
info.processor.architecture.c_str());
1607 fprintf(stdout,
"Processor cores : %d\n",
info.processor.cores);
1608 fprintf(stdout,
"Processor siblings : %d\n",
info.processor.siblings);
1609 fprintf(stdout,
"Processor Mhz : %.2lf\n\n",
info.processor.frequency);
1611 fprintf(stdout,
"Environment variables :\n%s\n",
info.platform.environmentVars.toString().c_str());
1619 if (config.
check(
"which"))
1623 Help(
"SYNTAX ERROR: missing remote server\n");
1633 if (!response.
size())
1640 if (config.
check(
"exit"))
1644 Help(
"SYNTAX ERROR: missing remote server\n");
1654 if (!response.
size())
1665void yarp::run::Run::Help(
const char *msg)
1667 fprintf(stderr,
"%s", msg);
1668 fprintf(stderr,
"\nUSAGE:\n\n");
1669 fprintf(stderr,
"yarp run --server SERVERPORT\nrun a server on the local machine\n\n");
1670 fprintf(stderr,
"yarp run --on SERVERPORT --as TAG --cmd COMMAND [ARGLIST] [--workdir WORKDIR] [--env ENVIRONMENT]\nrun a command on SERVERPORT server\n\n");
1671 fprintf(stderr,
"yarp run --on SERVERPORT --as TAG --stdio STDIOSERVERPORT [--hold] [--geometry WxH+X+Y] --cmd COMMAND [ARGLIST] [--workdir WORKDIR] [--env ENVIRONMENT]\n");
1672 fprintf(stderr,
"run a command on SERVERPORT server sending I/O to STDIOSERVERPORT server\n\n");
1673 fprintf(stderr,
"yarp run --on SERVERPORT --kill TAG SIGNUM\nsend SIGNUM signal to TAG command\n\n");
1674 fprintf(stderr,
"yarp run --on SERVERPORT --sigterm TAG\nterminate TAG command\n\n");
1675 fprintf(stderr,
"yarp run --on SERVERPORT --sigtermall\nterminate all commands\n\n");
1676 fprintf(stderr,
"yarp run --on SERVERPORT --ps\nreport commands running on SERVERPORT\n\n");
1677 fprintf(stderr,
"yarp run --on SERVERPORT --isrunning TAG\nTAG command is running?\n\n");
1678 fprintf(stderr,
"yarp run --on SERVERPORT --sysinfo\nreport system information of SERVERPORT\n\n");
1679 fprintf(stderr,
"yarp run --on SERVERPORT --exit\nstop SERVERPORT server\n\n");
1695 std::string strStdioUUID=msg.
find(
"stdiouuid").
asString();
1699 SECURITY_ATTRIBUTES pipe_sec_attr;
1700 pipe_sec_attr.nLength=
sizeof(SECURITY_ATTRIBUTES);
1701 pipe_sec_attr.bInheritHandle=TRUE;
1702 pipe_sec_attr.lpSecurityDescriptor =
nullptr;
1703 HANDLE read_from_pipe_stdin_to_cmd, write_to_pipe_stdin_to_cmd;
1704 CreatePipe(&read_from_pipe_stdin_to_cmd, &write_to_pipe_stdin_to_cmd, &pipe_sec_attr, 0);
1705 HANDLE read_from_pipe_cmd_to_stdout, write_to_pipe_cmd_to_stdout;
1706 CreatePipe(&read_from_pipe_cmd_to_stdout, &write_to_pipe_cmd_to_stdout, &pipe_sec_attr, 0);
1709 PROCESS_INFORMATION stdout_process_info;
1710 ZeroMemory(&stdout_process_info,
sizeof(PROCESS_INFORMATION));
1711 STARTUPINFO stdout_startup_info;
1712 ZeroMemory(&stdout_startup_info,
sizeof(STARTUPINFO));
1714 stdout_startup_info.cb=
sizeof(STARTUPINFO);
1715 stdout_startup_info.hStdError=GetStdHandle(STD_ERROR_HANDLE);
1716 stdout_startup_info.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
1717 stdout_startup_info.hStdInput=read_from_pipe_cmd_to_stdout;
1718 stdout_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1720 BOOL bSuccess=CreateProcess(
nullptr,
1721 (
char*)(std::string(
"yarprun --write ")+strStdioUUID).c_str(),
1725 CREATE_NEW_PROCESS_GROUP,
1728 &stdout_startup_info,
1729 &stdout_process_info);
1733 std::string strError=std::string(
"ABORTED: server=")+mPortName
1734 +std::string(
" alias=")+strAlias
1735 +std::string(
" cmd=stdout\n")
1736 +std::string(
"Can't execute stdout because ")+lastError2String()
1741 fprintf(stderr,
"%s", strError.c_str());
1744 CloseHandle(write_to_pipe_stdin_to_cmd);
1745 CloseHandle(read_from_pipe_stdin_to_cmd);
1746 CloseHandle(write_to_pipe_cmd_to_stdout);
1747 CloseHandle(read_from_pipe_cmd_to_stdout);
1754 PROCESS_INFORMATION stdin_process_info;
1755 ZeroMemory(&stdin_process_info,
sizeof(PROCESS_INFORMATION));
1756 STARTUPINFO stdin_startup_info;
1757 ZeroMemory(&stdin_startup_info,
sizeof(STARTUPINFO));
1759 stdin_startup_info.cb=
sizeof(STARTUPINFO);
1760 stdin_startup_info.hStdError=write_to_pipe_stdin_to_cmd;
1761 stdin_startup_info.hStdOutput=write_to_pipe_stdin_to_cmd;
1762 stdin_startup_info.hStdInput=GetStdHandle(STD_INPUT_HANDLE);
1763 stdin_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1765 bSuccess=CreateProcess(
nullptr,
1766 (
char*)(std::string(
"yarprun --read ")+strStdioUUID).c_str(),
1770 CREATE_NEW_PROCESS_GROUP,
1773 &stdin_startup_info,
1774 &stdin_process_info);
1778 std::string strError=std::string(
"ABORTED: server=")+mPortName
1779 +std::string(
" alias=")+strAlias
1780 +std::string(
" cmd=stdin\n")
1781 +std::string(
"Can't execute stdin because ")+lastError2String()
1786 fprintf(stderr,
"%s", strError.c_str());
1788 TerminateProcess(stdout_process_info.hProcess,
YARPRUN_ERROR);
1790 CloseHandle(stdout_process_info.hProcess);
1792 CloseHandle(write_to_pipe_stdin_to_cmd);
1793 CloseHandle(read_from_pipe_stdin_to_cmd);
1794 CloseHandle(write_to_pipe_cmd_to_stdout);
1795 CloseHandle(read_from_pipe_cmd_to_stdout);
1802 PROCESS_INFORMATION cmd_process_info;
1803 ZeroMemory(&cmd_process_info,
sizeof(PROCESS_INFORMATION));
1804 STARTUPINFO cmd_startup_info;
1805 ZeroMemory(&cmd_startup_info,
sizeof(STARTUPINFO));
1807 cmd_startup_info.cb=
sizeof(STARTUPINFO);
1808 cmd_startup_info.hStdError=write_to_pipe_cmd_to_stdout;
1809 cmd_startup_info.hStdOutput=write_to_pipe_cmd_to_stdout;
1810 cmd_startup_info.hStdInput=read_from_pipe_stdin_to_cmd;
1811 cmd_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1816 for (
int s=0; s<botCmd.
size(); ++s)
1818 strCmd+=botCmd.
get(s).
toString()+std::string(
" ");
1824 TCHAR chNewEnv[32767];
1827 LPTCH chOldEnv = GetEnvironmentStrings();
1830 LPTSTR lpOld = (LPTSTR) chOldEnv;
1831 LPTSTR lpNew = (LPTSTR) chNewEnv;
1834 lstrcpy(lpNew, lpOld);
1835 lpOld += lstrlen(lpOld) + 1;
1836 lpNew += lstrlen(lpNew) + 1;
1841 lstrcpy(lpNew, (LPTCH)
"YARP_IS_YARPRUN=1");
1842 lpNew += lstrlen(lpNew) + 1;
1846 lstrcpy(lpNew, (LPTCH)
"YARPRUN_IS_FORWARDING_LOG=1");
1847 lpNew += lstrlen(lpNew) + 1;
1850 std::string cstrEnvName;
1851 if (msg.
check(
"env"))
1854 for (
const auto& s : ss) {
1855 lstrcpy(lpNew, (LPTCH) s.c_str());
1856 lpNew += lstrlen(lpNew) + 1;
1863 bool bWorkdir=msg.
check(
"workdir");
1864 std::string strWorkdir=bWorkdir?msg.
find(
"workdir").
asString()+
"\\":
"";
1866 bSuccess=CreateProcess(
nullptr,
1867 (
char*)(strWorkdir+strCmd).c_str(),
1871 CREATE_NEW_PROCESS_GROUP,
1873 bWorkdir ? strWorkdir.c_str() : nullptr,
1877 if (!bSuccess && bWorkdir)
1879 bSuccess=CreateProcess(
nullptr,
1880 (
char*)(strCmd.c_str()),
1884 CREATE_NEW_PROCESS_GROUP,
1892 FreeEnvironmentStrings(chOldEnv);
1899 std::string line1=std::string(
"ABORTED: server=")+mPortName
1900 +std::string(
" alias=")+strAlias
1901 +std::string(
" cmd=")+strCmd
1902 +std::string(
"pid=")+
int2String(cmd_process_info.dwProcessId)
1905 WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line1.length(), &nBytes, 0);
1907 std::string line2=std::string(
"Can't execute command because ")+lastError2String()+std::string(
"\n");
1908 WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line2.length(), &nBytes, 0);
1909 FlushFileBuffers(write_to_pipe_cmd_to_stdout);
1911 std::string out=line1+line2;
1913 fprintf(stderr,
"%s", out.c_str());
1916 CloseHandle(write_to_pipe_stdin_to_cmd);
1917 CloseHandle(read_from_pipe_stdin_to_cmd);
1918 CloseHandle(write_to_pipe_cmd_to_stdout);
1919 CloseHandle(read_from_pipe_cmd_to_stdout);
1921 TerminateProcess(stdout_process_info.hProcess,
YARPRUN_ERROR);
1923 CloseHandle(stdout_process_info.hProcess);
1925 TerminateProcess(stdin_process_info.hProcess,
YARPRUN_ERROR);
1927 CloseHandle(stdin_process_info.hProcess);
1932 FlushFileBuffers(write_to_pipe_cmd_to_stdout);
1938 cmd_process_info.dwProcessId,
1941 stdin_process_info.dwProcessId,
1942 stdout_process_info.dwProcessId,
1943 read_from_pipe_stdin_to_cmd,
1944 write_to_pipe_stdin_to_cmd,
1945 read_from_pipe_cmd_to_stdout,
1946 write_to_pipe_cmd_to_stdout,
1947 cmd_process_info.hProcess,
1951 if (msg.
check(
"env"))
1955 mProcessVector.Add(pInf);
1957 result.
addInt32(cmd_process_info.dwProcessId);
1958 std::string out=std::string(
"STARTED: server=")+mPortName
1959 +std::string(
" alias=")+strAlias
1960 +std::string(
" cmd=")+strCmd
1961 +std::string(
" pid=")+
int2String(cmd_process_info.dwProcessId)
1966 fprintf(stderr,
"%s", out.c_str());
1968 return cmd_process_info.dwProcessId;
1976 std::string portName=
"/log";
1977 portName+=mPortName+
"/";
1979 command = command.substr(0, command.find(
' '));
1980 command = command.substr(command.find_last_of(
"\\/") + 1);
1982 if (proc_label !=
"") { portName +=
"[" + proc_label +
"]"; }
1985 SECURITY_ATTRIBUTES pipe_sec_attr;
1986 pipe_sec_attr.nLength=
sizeof(SECURITY_ATTRIBUTES);
1987 pipe_sec_attr.bInheritHandle=TRUE;
1988 pipe_sec_attr.lpSecurityDescriptor =
nullptr;
1989 HANDLE read_from_pipe_cmd_to_stdout, write_to_pipe_cmd_to_stdout;
1990 CreatePipe(&read_from_pipe_cmd_to_stdout, &write_to_pipe_cmd_to_stdout, &pipe_sec_attr, 0);
1993 PROCESS_INFORMATION stdout_process_info;
1994 ZeroMemory(&stdout_process_info,
sizeof(PROCESS_INFORMATION));
1995 STARTUPINFO stdout_startup_info;
1996 ZeroMemory(&stdout_startup_info,
sizeof(STARTUPINFO));
1998 stdout_startup_info.cb=
sizeof(STARTUPINFO);
1999 stdout_startup_info.hStdError=GetStdHandle(STD_ERROR_HANDLE);
2000 stdout_startup_info.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
2001 stdout_startup_info.hStdInput=read_from_pipe_cmd_to_stdout;
2002 stdout_startup_info.dwFlags|=STARTF_USESTDHANDLES;
2004 BOOL bSuccess=CreateProcess(
nullptr,
2005 (
char*)(std::string(
"yarprun --log ")+loggerName+std::string(
" --write ")+portName).c_str(),
2009 CREATE_NEW_PROCESS_GROUP,
2012 &stdout_startup_info,
2013 &stdout_process_info);
2017 std::string strError=std::string(
"ABORTED: server=")+mPortName
2018 +std::string(
" alias=")+strAlias
2019 +std::string(
" cmd=stdout\n")
2020 +std::string(
"Can't execute stdout because ")+lastError2String()
2025 fprintf(stderr,
"%s", strError.c_str());
2028 CloseHandle(write_to_pipe_cmd_to_stdout);
2029 CloseHandle(read_from_pipe_cmd_to_stdout);
2036 PROCESS_INFORMATION cmd_process_info;
2037 ZeroMemory(&cmd_process_info,
sizeof(PROCESS_INFORMATION));
2038 STARTUPINFO cmd_startup_info;
2039 ZeroMemory(&cmd_startup_info,
sizeof(STARTUPINFO));
2041 cmd_startup_info.cb=
sizeof(STARTUPINFO);
2042 cmd_startup_info.hStdError=write_to_pipe_cmd_to_stdout;
2043 cmd_startup_info.hStdOutput=write_to_pipe_cmd_to_stdout;
2044 cmd_startup_info.hStdInput=GetStdHandle(STD_INPUT_HANDLE);
2045 cmd_startup_info.dwFlags|=STARTF_USESTDHANDLES;
2050 for (
int s=0; s<botCmd.
size(); ++s)
2052 strCmd+=botCmd.
get(s).
toString()+std::string(
" ");
2058 TCHAR chNewEnv[32767];
2061 LPTCH chOldEnv = GetEnvironmentStrings();
2064 LPTSTR lpOld = (LPTSTR) chOldEnv;
2065 LPTSTR lpNew = (LPTSTR) chNewEnv;
2068 lstrcpy(lpNew, lpOld);
2069 lpOld += lstrlen(lpOld) + 1;
2070 lpNew += lstrlen(lpNew) + 1;
2075 lstrcpy(lpNew, (LPTCH)
"YARP_IS_YARPRUN=1");
2076 lpNew += lstrlen(lpNew) + 1;
2080 lstrcpy(lpNew, (LPTCH)
"YARPRUN_IS_FORWARDING_LOG=1");
2081 lpNew += lstrlen(lpNew) + 1;
2084 std::string cstrEnvName;
2085 if (msg.
check(
"env"))
2088 for (
const auto& s : ss) {
2089 lstrcpy(lpNew, (LPTCH)s.c_str());
2090 lpNew += lstrlen(lpNew) + 1;
2097 bool bWorkdir=msg.
check(
"workdir");
2098 std::string strWorkdir=bWorkdir?msg.
find(
"workdir").
asString()+
"\\":
"";
2100 bSuccess=CreateProcess(
nullptr,
2101 (
char*)(strWorkdir+strCmd).c_str(),
2105 CREATE_NEW_PROCESS_GROUP,
2107 bWorkdir?strWorkdir.c_str():nullptr,
2111 if (!bSuccess && bWorkdir)
2113 bSuccess=CreateProcess(
nullptr,
2114 (
char*)(strCmd.c_str()),
2118 CREATE_NEW_PROCESS_GROUP,
2126 FreeEnvironmentStrings(chOldEnv);
2133 std::string line1=std::string(
"ABORTED: server=")+mPortName
2134 +std::string(
" alias=")+strAlias
2135 +std::string(
" cmd=")+strCmd
2136 +std::string(
"pid=")+
int2String(cmd_process_info.dwProcessId)
2139 WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line1.length(), &nBytes, 0);
2141 std::string line2=std::string(
"Can't execute command because ")+lastError2String()+std::string(
"\n");
2142 WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line2.length(), &nBytes, 0);
2143 FlushFileBuffers(write_to_pipe_cmd_to_stdout);
2145 std::string out=line1+line2;
2147 fprintf(stderr,
"%s", out.c_str());
2150 CloseHandle(write_to_pipe_cmd_to_stdout);
2151 CloseHandle(read_from_pipe_cmd_to_stdout);
2153 TerminateProcess(stdout_process_info.hProcess,
YARPRUN_ERROR);
2155 CloseHandle(stdout_process_info.hProcess);
2160 FlushFileBuffers(write_to_pipe_cmd_to_stdout);
2166 cmd_process_info.dwProcessId,
2167 stdout_process_info.dwProcessId,
2168 read_from_pipe_cmd_to_stdout,
2169 write_to_pipe_cmd_to_stdout,
2170 cmd_process_info.hProcess,
2177 if (msg.
check(
"env"))
2181 mProcessVector.Add(pInf);
2183 result.
addInt32(cmd_process_info.dwProcessId);
2184 std::string out=std::string(
"STARTED: server=")+mPortName
2185 +std::string(
" alias=")+strAlias
2186 +std::string(
" cmd=")+strCmd
2187 +std::string(
" pid=")+
int2String(cmd_process_info.dwProcessId)
2192 fprintf(stderr,
"%s", out.c_str());
2194 return cmd_process_info.dwProcessId;
2200 std::string strAlias=msg.
find(
"as").
asString().c_str();
2203 PROCESS_INFORMATION cmd_process_info;
2204 ZeroMemory(&cmd_process_info,
sizeof(PROCESS_INFORMATION));
2205 STARTUPINFO cmd_startup_info;
2206 ZeroMemory(&cmd_startup_info,
sizeof(STARTUPINFO));
2208 cmd_startup_info.cb=
sizeof(STARTUPINFO);
2213 for (
int s=0; s<botCmd.
size(); ++s)
2215 strCmd+=botCmd.
get(s).
toString()+std::string(
" ");
2221 TCHAR chNewEnv[32767];
2224 LPTCH chOldEnv = GetEnvironmentStrings();
2227 LPTSTR lpOld = (LPTSTR) chOldEnv;
2228 LPTSTR lpNew = (LPTSTR) chNewEnv;
2231 lstrcpy(lpNew, lpOld);
2232 lpOld += lstrlen(lpOld) + 1;
2233 lpNew += lstrlen(lpNew) + 1;
2238 lstrcpy(lpNew, (LPTCH)
"YARP_IS_YARPRUN=1");
2239 lpNew += lstrlen(lpNew) + 1;
2243 lstrcpy(lpNew, (LPTCH)
"YARPRUN_IS_FORWARDING_LOG=0");
2244 lpNew += lstrlen(lpNew) + 1;
2247 std::string cstrEnvName;
2248 if (msg.
check(
"env"))
2251 for (
const auto& s : ss) {
2252 lstrcpy(lpNew, (LPTCH)s.c_str());
2253 lpNew += lstrlen(lpNew) + 1;
2260 bool bWorkdir=msg.
check(
"workdir");
2261 std::string strWorkdir=bWorkdir?msg.
find(
"workdir").
asString()+
"\\":
"";
2263 BOOL bSuccess=CreateProcess(
nullptr,
2264 (
char*)(strWorkdir+strCmd).c_str(),
2268 CREATE_NEW_PROCESS_GROUP,
2270 bWorkdir ? strWorkdir.c_str() : nullptr,
2274 if (!bSuccess && bWorkdir)
2276 bSuccess=CreateProcess(
nullptr,
2277 (
char*)(strCmd.c_str()),
2281 CREATE_NEW_PROCESS_GROUP,
2289 FreeEnvironmentStrings(chOldEnv);
2295 std::string out=std::string(
"ABORTED: server=")+mPortName
2296 +std::string(
" alias=")+strAlias
2297 +std::string(
" cmd=")+strCmd
2298 +std::string(
" pid=")+
int2String(cmd_process_info.dwProcessId)
2299 +std::string(
"\nCan't execute command because ")+lastError2String()
2303 fprintf(stderr,
"%s", out.c_str());
2312 cmd_process_info.dwProcessId,
2313 cmd_process_info.hProcess,
2316 if (msg.
check(
"env"))
2319 mProcessVector.Add(pInf);
2321 result.
addInt32(cmd_process_info.dwProcessId);
2322 std::string out=std::string(
"STARTED: server=")+mPortName
2323 +std::string(
" alias=")+strAlias
2324 +std::string(
" cmd=")+strCmd
2325 +std::string(
" pid=")+
int2String(cmd_process_info.dwProcessId)
2328 fprintf(stderr,
"%s", out.c_str());
2330 return cmd_process_info.dwProcessId;
2336 PROCESS_INFORMATION stdio_process_info;
2337 ZeroMemory(&stdio_process_info,
sizeof(PROCESS_INFORMATION));
2339 STARTUPINFO stdio_startup_info;
2340 ZeroMemory(&stdio_startup_info,
sizeof(STARTUPINFO));
2341 stdio_startup_info.cb=
sizeof(STARTUPINFO);
2342 stdio_startup_info.wShowWindow=SW_SHOWNOACTIVATE;
2343 stdio_startup_info.dwFlags=STARTF_USESHOWWINDOW;
2347 std::string strCmd=std::string(
"yarprun --readwrite ")+strUUID;
2350 BOOL bSuccess=CreateProcess(
nullptr,
2351 (
char*)strCmd.c_str(),
2358 &stdio_startup_info,
2359 &stdio_process_info);
2367 stdio_process_info.dwProcessId,
2368 stdio_process_info.hProcess,
2371 out=std::string(
"STARTED: server=")+mPortName
2372 +std::string(
" alias=")+strAlias
2373 +std::string(
" cmd=stdio pid=")+
int2String(stdio_process_info.dwProcessId)
2380 out=std::string(
"ABORTED: server=")+mPortName
2381 +std::string(
" alias=")+strAlias
2382 +std::string(
" cmd=stdio\n")
2383 +std::string(
"Can't open stdio window because ")+lastError2String()
2388 result.
addInt32(stdio_process_info.dwProcessId);
2390 fprintf(stderr,
"%s", out.c_str());
2393 return stdio_process_info.dwProcessId;
2404 char *pTmp = strchr(pLine,
' ');
2409 while ((*pTmp) && (*pTmp ==
' ')) {
2412 if (*pTmp ==
'\0') {
2424 char *pNext = io_pLine;
2428 size_t len = strlen(io_pLine);
2431 for(i = 0; i < len; i++) {
2432 if ((!quoted) && (
'"' == io_pLine[i])) {
2435 }
else if ((quoted) && (
'"' == io_pLine[i])) {
2438 }
else if ((quoted) && (
' ' == io_pLine[i])) {
2444 memset(o_pArgv, 0x00,
sizeof(
char*) *
C_MAXARGS);
2446 o_pArgv[0] = io_pLine;
2448 while ((
nullptr != pNext) && (*o_pArgc <
C_MAXARGS)) {
2450 pNext = o_pArgv[*o_pArgc];
2452 if (
nullptr != o_pArgv[*o_pArgc]) {
2457 for(j = 0; j < *o_pArgc; j++) {
2458 len = strlen(o_pArgv[j]);
2459 for(i = 0; i < len; i++) {
2460 if (
'\1' == o_pArgv[j][i]) {
2461 o_pArgv[j][i] =
' ';
2467void yarp::run::Run::CleanZombie(
int pid)
2469 bool bFound=mProcessVector && mProcessVector->CleanZombie(pid);
2473 mStdioVector->CleanZombie(pid);
2485 std::string strStdioUUID=msg.
find(
"stdiouuid").
asString();
2487 int pipe_stdin_to_cmd[2];
2488 int ret_stdin_to_cmd=yarp::run::impl::pipe(pipe_stdin_to_cmd);
2490 int pipe_cmd_to_stdout[2];
2491 int ret_cmd_to_stdout=yarp::run::impl::pipe(pipe_cmd_to_stdout);
2493 int pipe_child_to_parent[2];
2494 int ret_child_to_parent=yarp::run::impl::pipe(pipe_child_to_parent);
2496 if (ret_child_to_parent!=0 || ret_cmd_to_stdout!=0 || ret_stdin_to_cmd!=0)
2500 std::string out=std::string(
"ABORTED: server=")+mPortName
2501 +std::string(
" alias=")+strAlias
2502 +std::string(
" cmd=stdout\n")
2503 +std::string(
"Can't create pipes ")+strerror(
error)
2508 fprintf(stderr,
"%s", out.c_str());
2513 int pid_stdout=yarp::run::impl::fork();
2515 if (IS_INVALID(pid_stdout))
2526 std::string out=std::string(
"ABORTED: server=")+mPortName
2527 +std::string(
" alias=")+strAlias
2528 +std::string(
" cmd=stdout\n")
2529 +std::string(
"Can't fork stdout process because ")+strerror(
error)
2534 fprintf(stderr,
"%s", out.c_str());
2539 if (IS_NEW_PROCESS(pid_stdout))
2555 int ret = yarp::run::impl::execlp(
"yarprun",
"yarprun",
"--write", strStdioUUID.c_str(),
static_cast<char*
>(
nullptr));
2563 std::string out=std::string(
"ABORTED: server=")+mPortName
2564 +std::string(
" alias=")+strAlias
2565 +std::string(
" cmd=stdout\n")
2566 +std::string(
"Can't execute stdout because ")+strerror(
error)
2569 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
2570 fprintf(out_to_parent,
"%s", out.c_str());
2571 fflush(out_to_parent);
2572 fclose(out_to_parent);
2574 fprintf(stderr,
"%s", out.c_str());
2582 if (IS_PARENT_OF(pid_stdout))
2586 fprintf(stderr,
"STARTED: server=%s alias=%s cmd=stdout pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdout);
2588 int pid_stdin=yarp::run::impl::fork();
2590 if (IS_INVALID(pid_stdin))
2600 std::string out=std::string(
"ABORTED: server=")+mPortName
2601 +std::string(
" alias=")+strAlias
2602 +std::string(
" cmd=stdin\n")
2603 +std::string(
"Can't fork stdin process because ")+strerror(
error)
2608 fprintf(stderr,
"%s", out.c_str());
2610 SIGNAL(pid_stdout, SIGTERM);
2611 fprintf(stderr,
"TERMINATING stdout (%d)\n", pid_stdout);
2616 if (IS_NEW_PROCESS(pid_stdin))
2633 int ret = yarp::run::impl::execlp(
"yarprun",
"yarprun",
"--read", strStdioUUID.c_str(),
static_cast<char*
>(
nullptr));
2641 std::string out=std::string(
"ABORTED: server=")+mPortName
2642 +std::string(
" alias=")+strAlias
2643 +std::string(
" cmd=stdin\n")
2644 +std::string(
"Can't execute stdin because ")+strerror(
error)
2648 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
2649 fprintf(out_to_parent,
"%s", out.c_str());
2650 fflush(out_to_parent);
2651 fclose(out_to_parent);
2652 fprintf(stderr,
"%s", out.c_str());
2660 if (IS_PARENT_OF(pid_stdin))
2665 fprintf(stderr,
"STARTED: server=%s alias=%s cmd=stdin pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdin);
2667 int pid_cmd=yarp::run::impl::fork();
2669 if (IS_INVALID(pid_cmd))
2677 std::string out=std::string(
"ABORTED: server=")+mPortName
2678 +std::string(
" alias=")+strAlias
2679 +std::string(
" cmd=")+strCmd
2680 +std::string(
"\nCan't fork command process because ")+strerror(
error)
2685 fprintf(stderr,
"%s", out.c_str());
2687 FILE* to_yarp_stdout=fdopen(pipe_cmd_to_stdout[
WRITE_TO_PIPE],
"w");
2688 fprintf(to_yarp_stdout,
"%s", out.c_str());
2689 fflush(to_yarp_stdout);
2690 fclose(to_yarp_stdout);
2692 SIGNAL(pid_stdout, SIGTERM);
2693 fprintf(stderr,
"TERMINATING stdout (%d)\n", pid_stdout);
2694 SIGNAL(pid_stdin, SIGTERM);
2695 fprintf(stderr,
"TERMINATING stdin (%d)\n", pid_stdin);
2702 if (IS_NEW_PROCESS(pid_cmd))
2706 char *cmd_str=
new char[strCmd.length()+1];
2707 strcpy(cmd_str, strCmd.c_str());
2715 char **arg_str =
new char*[
C_MAXARGS + 1];
2717 arg_str[nargs]=
nullptr;
2719 setvbuf(stdout,
nullptr, _IONBF, 0);
2733 if (msg.
check(
"env"))
2736 for (
const auto& s : ss) {
2737 char* szenv =
new char[s.size()+1];
2738 strcpy(szenv, s.c_str());
2739 yarp::run::impl::putenv(szenv);
2744 if (msg.
check(
"workdir"))
2746 int ret = yarp::os::impl::chdir(msg.
find(
"workdir").
asString().c_str());
2752 std::string out=std::string(
"ABORTED: server=")+mPortName
2753 +std::string(
" alias=")+strAlias
2754 +std::string(
" cmd=")+strCmd
2755 +std::string(
"\nCan't execute command, cannot set working directory ")+strerror(
error)
2758 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
2759 fprintf(out_to_parent,
"%s", out.c_str());
2760 fflush(out_to_parent);
2761 fclose(out_to_parent);
2762 fprintf(stderr,
"%s", out.c_str());
2770 char currWorkDirBuff[1024];
2771 char *currWorkDir=yarp::os::impl::getcwd(currWorkDirBuff, 1024);
2775 char **cwd_arg_str=
new char*[nargs+1];
2776 for (
int i = 1; i < nargs; ++i) {
2777 cwd_arg_str[i] = arg_str[i];
2779 cwd_arg_str[nargs]=
nullptr;
2780 cwd_arg_str[0]=
new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
2782 strcpy(cwd_arg_str[0], currWorkDir);
2783 strcat(cwd_arg_str[0],
"/");
2784 strcat(cwd_arg_str[0], arg_str[0]);
2791 ret = yarp::run::impl::execvp(cwd_arg_str[0], cwd_arg_str);
2793 delete [] cwd_arg_str[0];
2794 delete [] cwd_arg_str;
2804 ret = yarp::run::impl::execvp(arg_str[0], arg_str);
2816 std::string out=std::string(
"ABORTED: server=")+mPortName
2817 +std::string(
" alias=")+strAlias
2818 +std::string(
" cmd=")+strCmd
2819 +std::string(
"\nCan't execute command because ")+strerror(
error)
2822 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
2823 fprintf(out_to_parent,
"%s", out.c_str());
2824 fflush(out_to_parent);
2825 fclose(out_to_parent);
2826 fprintf(stderr,
"%s", out.c_str());
2838 if (IS_PARENT_OF(pid_cmd))
2863 if (msg.
check(
"env"))
2868 mProcessVector->Add(pInf);
2872 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
2873 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
2874 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
2884 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
2888 out+=std::string(buff);
2891 fclose(in_from_child);
2900 out=std::string(
"STARTED: server=")+mPortName
2901 +std::string(
" alias=")+strAlias
2902 +std::string(
" cmd=")+strCmd
2911 fprintf(stderr,
"%s", out.c_str());
2921 result.
addString(
"I should never reach this point!!!\n");
2933 std::string portName=
"/log";
2934 portName+=mPortName+
"/";
2936 std::string command = strCmd;
2937 command = command.substr(0, command.find(
' '));
2938 command = command.substr(command.find_last_of(
"\\/") + 1);
2941 if (proc_label !=
"") { portName +=
"[" + proc_label +
"]"; }
2944 int pipe_cmd_to_stdout[2];
2945 int ret_cmd_to_stdout=yarp::run::impl::pipe(pipe_cmd_to_stdout);
2947 int pipe_child_to_parent[2];
2948 int ret_child_to_parent=yarp::run::impl::pipe(pipe_child_to_parent);
2950 if (ret_child_to_parent!=0 || ret_cmd_to_stdout!=0)
2954 std::string out=std::string(
"ABORTED: server=")+mPortName
2955 +std::string(
" alias=")+strAlias
2956 +std::string(
" cmd=stdout\n")
2957 +std::string(
"Can't create pipes ")+strerror(
error)
2962 fprintf(stderr,
"%s", out.c_str());
2967 int pid_stdout=yarp::run::impl::fork();
2969 if (IS_INVALID(pid_stdout))
2978 std::string out=std::string(
"ABORTED: server=")+mPortName
2979 +std::string(
" alias=")+strAlias
2980 +std::string(
" cmd=stdout\n")
2981 +std::string(
"Can't fork stdout process because ")+strerror(
error)
2986 fprintf(stderr,
"%s", out.c_str());
2991 if (IS_NEW_PROCESS(pid_stdout))
3005 int ret = yarp::run::impl::execlp(
"yarprun",
"yarprun",
"--write", portName.c_str(),
"--log", loggerName.c_str(),
static_cast<char*
>(
nullptr));
3013 std::string out=std::string(
"ABORTED: server=")+mPortName
3014 +std::string(
" alias=")+strAlias
3015 +std::string(
" cmd=stdout\n")
3016 +std::string(
"Can't execute stdout because ")+strerror(
error)
3019 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3020 fprintf(out_to_parent,
"%s", out.c_str());
3021 fflush(out_to_parent);
3022 fclose(out_to_parent);
3024 fprintf(stderr,
"%s", out.c_str());
3032 if (IS_PARENT_OF(pid_stdout))
3036 fprintf(stderr,
"STARTED: server=%s alias=%s cmd=stdout pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdout);
3042 int pid_cmd=yarp::run::impl::fork();
3044 if (IS_INVALID(pid_cmd))
3051 std::string out=std::string(
"ABORTED: server=")+mPortName
3052 +std::string(
" alias=")+strAlias
3053 +std::string(
" cmd=")+strCmd
3054 +std::string(
"\nCan't fork command process because ")+strerror(
error)
3059 fprintf(stderr,
"%s", out.c_str());
3061 FILE* to_yarp_stdout=fdopen(pipe_cmd_to_stdout[
WRITE_TO_PIPE],
"w");
3062 fprintf(to_yarp_stdout,
"%s", out.c_str());
3063 fflush(to_yarp_stdout);
3064 fclose(to_yarp_stdout);
3066 SIGNAL(pid_stdout, SIGTERM);
3067 fprintf(stderr,
"TERMINATING stdout (%d)\n", pid_stdout);
3073 if (IS_NEW_PROCESS(pid_cmd))
3077 char *cmd_str=
new char[strCmd.length()+1];
3078 strcpy(cmd_str, strCmd.c_str());
3086 char **arg_str =
new char*[
C_MAXARGS + 1];
3088 arg_str[nargs]=
nullptr;
3090 setvbuf(stdout,
nullptr, _IONBF, 0);
3103 if (msg.
check(
"env"))
3106 for (
const auto& s : ss) {
3107 char* szenv =
new char[s.size()+1];
3108 strcpy(szenv, s.c_str());
3109 yarp::run::impl::putenv(szenv);
3114 if (msg.
check(
"workdir"))
3116 int ret = yarp::os::impl::chdir(msg.
find(
"workdir").
asString().c_str());
3122 std::string out=std::string(
"ABORTED: server=")+mPortName
3123 +std::string(
" alias=")+strAlias
3124 +std::string(
" cmd=")+strCmd
3125 +std::string(
"\nCan't execute command, cannot set working directory ")+strerror(
error)
3128 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3129 fprintf(out_to_parent,
"%s", out.c_str());
3130 fflush(out_to_parent);
3131 fclose(out_to_parent);
3132 fprintf(stderr,
"%s", out.c_str());
3140 char currWorkDirBuff[1024];
3141 char *currWorkDir=
getcwd(currWorkDirBuff, 1024);
3145 char **cwd_arg_str=
new char*[nargs+1];
3146 for (
int i = 1; i < nargs; ++i) {
3147 cwd_arg_str[i] = arg_str[i];
3149 cwd_arg_str[nargs]=
nullptr;
3150 cwd_arg_str[0]=
new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
3152 strcpy(cwd_arg_str[0], currWorkDir);
3153 strcat(cwd_arg_str[0],
"/");
3154 strcat(cwd_arg_str[0], arg_str[0]);
3161 ret = yarp::run::impl::execvp(cwd_arg_str[0], cwd_arg_str);
3163 delete [] cwd_arg_str[0];
3164 delete [] cwd_arg_str;
3174 ret = yarp::run::impl::execvp(arg_str[0], arg_str);
3185 std::string out=std::string(
"ABORTED: server=")+mPortName
3186 +std::string(
" alias=")+strAlias
3187 +std::string(
" cmd=")+strCmd
3188 +std::string(
"\nCan't execute command because ")+strerror(
error)
3191 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3192 fprintf(out_to_parent,
"%s", out.c_str());
3193 fflush(out_to_parent);
3194 fclose(out_to_parent);
3195 fprintf(stderr,
"%s", out.c_str());
3207 if (IS_PARENT_OF(pid_cmd))
3226 if (msg.
check(
"env"))
3231 mProcessVector->Add(pInf);
3235 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
3236 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
3237 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3247 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
3251 out+=std::string(buff);
3254 fclose(in_from_child);
3263 out=std::string(
"STARTED: server=")+mPortName
3264 +std::string(
" alias=")+strAlias
3265 +std::string(
" cmd=")+strCmd
3273 fprintf(stderr,
"%s", out.c_str());
3283 result.
addString(
"I should never reach this point!!!\n");
3295 if (msg.
check(
"forward"))
3297 strCmd=std::string(
"/bin/bash -l -c \"yarprun --readwrite ")+strUUID
3302 strCmd=std::string(
"/bin/bash -l -c \"yarprun --readwrite ")+strUUID+
"\"";
3305 int pipe_child_to_parent[2];
3307 if (yarp::run::impl::pipe(pipe_child_to_parent))
3311 std::string out=std::string(
"ABORTED: server=")+mPortName
3312 +std::string(
" alias=")+strAlias
3313 +std::string(
" cmd=stdio\nCan't create pipe ")+strerror(
error)
3319 fprintf(stderr,
"%s", out.c_str());
3326 for (
auto & i : command) {
3330 cmdcpy(command[c++],
"xterm");
3331 cmdcpy(command[c++], msg.
check(
"hold")?
"-hold":
"+hold");
3333 if (msg.
check(
"geometry"))
3335 cmdcpy(command[c++],
"-geometry");
3336 cmdcpy(command[c++], msg.
find(
"geometry").
asString().c_str());
3339 cmdcpy(command[c++],
"-title");
3340 cmdcpy(command[c++], strAlias.c_str());
3342 cmdcpy(command[c++],
"-e");
3343 cmdcpy(command[c++], strCmd.c_str());
3345 int pid_cmd=yarp::run::impl::fork();
3347 if (IS_INVALID(pid_cmd))
3351 std::string out=std::string(
"ABORTED: server=")+mPortName
3352 +std::string(
" alias=")+strAlias
3353 +std::string(
" cmd=stdio\nCan't fork stdout process because ")+strerror(
error)
3359 fprintf(stderr,
"%s", out.c_str());
3369 if (IS_NEW_PROCESS(pid_cmd))
3384 int ret = yarp::run::impl::execvp(
"xterm", command);
3392 std::string out=std::string(
"ABORTED: server=")+mPortName
3393 +std::string(
" alias=")+strAlias
3394 +std::string(
" cmd=xterm\nCan't execute command because ")+strerror(
error)
3397 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3399 fprintf(out_to_parent,
"%s", out.c_str());
3400 fflush(out_to_parent);
3401 fclose(out_to_parent);
3403 fprintf(stderr,
"%s", out.c_str());
3411 if (IS_PARENT_OF(pid_cmd))
3415 mStdioVector->Add(
new YarpRunProcInfo(strAlias, mPortName, pid_cmd,
nullptr, msg.
check(
"hold")));
3423 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
3424 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
3425 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3434 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
3438 out+=std::string(buff);
3441 fclose(in_from_child);
3447 if (out.substr(0, 14)==
"xterm Xt error" || out.substr(0, 7)==
"ABORTED")
3453 out=std::string(
"STARTED: server=")+mPortName
3454 +std::string(
" alias=")+strAlias
3455 +std::string(
" cmd=xterm pid=")+
int2String(pid_cmd)
3460 fprintf(stderr,
"%s", out.c_str());
3481 int pipe_child_to_parent[2];
3482 int ret_pipe_child_to_parent=yarp::run::impl::pipe(pipe_child_to_parent);
3484 if (ret_pipe_child_to_parent!=0)
3488 std::string out=std::string(
"ABORTED: server=")+mPortName
3489 +std::string(
" alias=")+strAlias
3490 +std::string(
" cmd=stdio\nCan't create pipe ")+strerror(
error)
3496 fprintf(stderr,
"%s", out.c_str());
3501 int pid_cmd=yarp::run::impl::fork();
3503 if (IS_INVALID(pid_cmd))
3507 std::string out=std::string(
"ABORTED: server=")+mPortName
3508 +std::string(
" alias=")+strAlias
3509 +std::string(
" cmd=")+strCmd
3510 +std::string(
"\nCan't fork command process because ")+strerror(
error)
3515 fprintf(stderr,
"%s", out.c_str());
3520 if (IS_NEW_PROCESS(pid_cmd))
3522 int saved_stderr = yarp::run::impl::dup(STDERR_FILENO);
3523 int null_file=open(
"/dev/null", O_WRONLY);
3530 char *cmd_str=
new char[strCmd.length()+1];
3531 strcpy(cmd_str, strCmd.c_str());
3539 char **arg_str =
new char*[
C_MAXARGS + 1];
3541 arg_str[nargs]=
nullptr;
3551 if (msg.
check(
"env"))
3554 for (
const auto& s : ss) {
3555 char* szenv =
new char[s.size()+1];
3556 strcpy(szenv, s.c_str());
3557 yarp::run::impl::putenv(szenv);
3561 if (msg.
check(
"workdir"))
3563 int ret = yarp::os::impl::chdir(msg.
find(
"workdir").
asString().c_str());
3569 std::string out=std::string(
"ABORTED: server=")+mPortName
3570 +std::string(
" alias=")+strAlias
3571 +std::string(
" cmd=")+strCmd
3572 +std::string(
"\nCan't execute command, cannot set working directory ")+strerror(
error)
3575 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3576 fprintf(out_to_parent,
"%s", out.c_str());
3577 fflush(out_to_parent);
3578 fclose(out_to_parent);
3581 fprintf(stderr,
"%s", out.c_str());
3587 char currWorkDirBuff[1024];
3588 char *currWorkDir=
getcwd(currWorkDirBuff, 1024);
3592 char **cwd_arg_str=
new char*[nargs+1];
3593 for (
int i = 1; i < nargs; ++i) {
3594 cwd_arg_str[i] = arg_str[i];
3596 cwd_arg_str[nargs]=
nullptr;
3597 cwd_arg_str[0]=
new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
3600 strcpy(cwd_arg_str[0], currWorkDir);
3601 strcat(cwd_arg_str[0],
"/");
3602 strcat(cwd_arg_str[0], arg_str[0]);
3609 ret = yarp::run::impl::execvp(cwd_arg_str[0], cwd_arg_str);
3611 delete [] cwd_arg_str[0];
3612 delete [] cwd_arg_str;
3621 ret = yarp::run::impl::execvp(arg_str[0], arg_str);
3628 std::string out=std::string(
"ABORTED: server=")+mPortName
3629 +std::string(
" alias=")+strAlias
3630 +std::string(
" cmd=")+strCmd
3631 +std::string(
"\nCan't execute command because ")+strerror(
error)
3634 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3635 fprintf(out_to_parent,
"%s", out.c_str());
3636 fflush(out_to_parent);
3637 fclose(out_to_parent);
3639 if (saved_stderr >= 0)
3643 fprintf(stderr,
"%s", out.c_str());
3652 if (IS_PARENT_OF(pid_cmd))
3654 auto* pInf =
new YarpRunProcInfo(strAlias, mPortName, pid_cmd,
nullptr,
false);
3656 if (msg.
check(
"env")) {
3659 mProcessVector->Add(pInf);
3661 sprintf(pidstr,
"%d", pid_cmd);
3665 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
3666 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
3667 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3677 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
3681 out+=std::string(buff);
3684 fclose(in_from_child);
3693 out=std::string(
"STARTED: server=")+mPortName
3694 +std::string(
" alias=")+strAlias
3695 +std::string(
" cmd=")+strCmd
3700 fprintf(stderr,
"%s", out.c_str());
3731 std::string dest_srv=node;
3733 if (command.
check(
"stdio"))
3735 dest_srv=std::string(command.
find(
"stdio").
asString());
3742 if (command.
check(
"geometry"))
3750 if (command.
check(
"hold"))
3769 printf(
":: %s\n", msg.
toString().c_str());
3771 response=sendMsg(msg, dest_srv);
3774 sprintf(buff,
"%d", response.
get(0).
asInt32());
3775 keyv=std::string(buff);
3794 printf(
":: %s\n", msg.
toString().c_str());
3796 response=sendMsg(msg, node);
3814 printf(
":: %s\n", msg.
toString().c_str());
3816 response=sendMsg(msg, node);
3836 printf(
":: %s\n", msg.
toString().c_str());
3838 response=sendMsg(msg, node);
3857 printf(
":: %s\n", msg.
toString().c_str());
3859 response=sendMsg(msg, node);
3861 if (!response.
size()) {
std::string toString(const T &value)
convert an arbitrary type to string.
int SIGNAL(int pid, int signum)
std::string int2String(int x)
static yarp::os::Bottle parsePaths(const std::string &txt)
void sigstdio_handler(int sig)
void sigint_handler(int sig)
constexpr fs::value_type slash
static std::string getProcLabel(const yarp::os::Bottle &msg)
void parseArguments(char *io_pLine, int *o_pArgc, char **o_pArgv)
Breaks up a line into multiple arguments.
static bool fileExists(const char *fname)
void splitLine(char *pLine, char **pArgs)
Split a line into separate words.
#define REDIRECT_TO(from, to)
static RunTerminator * pTerminator
void sigchld_handler(int)
An error handler that reaps the zombies.
void setEnv(const std::string &env)
void setCmd(const std::string &cmd)
A simple collection of objects that can be described and transmitted in a portable way.
void fromString(const std::string &text)
Initializes bottle from a string.
void append(const Bottle &alt)
Append the content of the given bottle to the current list.
Bottle & addList()
Places an empty nested list in the bottle, at the end of the list.
size_type size() const
Gets the number of elements in the bottle.
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Bottle & findGroup(const std::string &key) const override
Gets a list corresponding to a given keyword.
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Bottle tail() const
Get all but the first element of a bottle.
void clear()
Empties the bottle of any objects it contains.
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
void addString(const char *str)
Places a string in the bottle, at the end of the list.
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
A mini-server for performing network communication in the background.
static bool getLocalMode()
Get current value of flag "localMode", see setLocalMode function.
static bool connect(const std::string &src, const std::string &dest, const std::string &carrier="", bool quiet=true)
Request that an output port connect to an input port.
static bool checkNetwork()
Check if the YARP Network is up and running.
static bool disconnect(const std::string &src, const std::string &dest, bool quiet)
Request that an output port disconnect from an input port.
A class for storing options and configuration information.
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
std::string toString() const override
Return a standard text representation of the content of the object.
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Bottle & findGroup(const std::string &key) const override
Gets a list corresponding to a given keyword.
void unput(const std::string &key)
Remove the association from the given key to a value, if present.
void fromCommand(int argc, char *argv[], bool skipFirst=true, bool wipe=true)
Interprets a list of command arguments as a list of properties.
A port that is specialized as an RPC client.
A port that is specialized as an RPC server.
A class for thread synchronization and mutual exclusion.
static void delaySystem(double seconds)
A helper class to pass the SystemInfo object around the YARP network.
bool stop()
Stop the thread.
bool start()
Start the new thread running.
A single value (typically within a Bottle).
virtual std::int32_t asInt32() const
Get 32-bit integer value.
std::string toString() const override
Return a standard text representation of the content of the object.
virtual std::string asString() const
Get string value.
static NameClient & getNameClient()
Get an instance of the name client.
static int kill(const std::string &node, const std::string &keyv, int s)
Send a SIGNAL to an application running on a yarprun server (Linux only).
static int start(const std::string &node, yarp::os::Property &command, std::string &keyv)
Launch a yarprun server.
static bool isRunning(const std::string &node, std::string &keyv)
Get a report of all applications running on a yarprun server.
static int sigterm(const std::string &node, const std::string &keyv)
Terminate an application running on a yarprun server.
static int client(yarp::os::Property &config)
Send a property object to a run server, bundling up all the settings usually specified on the command...
static constexpr char path_separator
bool set_string(const std::string &key, const std::string &value)
Set a string to an environment variable.
std::string get_string(const std::string &key, bool *found=nullptr)
Read a string from an environment variable.
static constexpr value_type preferred_separator
ContainerT split(const typename ContainerT::value_type &s, std::basic_regex< typename ContainerT::value_type::value_type > regex)
Utility to split a string by a separator, into a vector of strings.
void useSystemClock()
Configure YARP to use system time (this is the default).
char * getcwd(char *buf, size_t size)
Portable wrapper for the getcwd() function.
int getpid()
Portable wrapper for the getppid() function.
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
bool write(const ImageOf< PixelRgb > &src, const std::string &dest, image_fileformat format=FORMAT_PPM)
The main, catch-all namespace for YARP.