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")
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;
530 if (!pServerPort) break;
538 if (msg.check("stdio"))
540 std::string strOnPort=msg.find(
"on").asString();
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));
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());
1582 fprintf(stdout,
"Platform release : %s\n", info.
platform.
release.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());
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);
1602 fprintf(stdout,
"Processor model : %s\n", info.
processor.
model.c_str());
1605 fprintf(stdout,
"Processor vendor : %s\n", info.
processor.
vendor.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());
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);
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))
2632 int ret = yarp::run::impl::execlp(
"yarprun",
"yarprun",
"--read", strStdioUUID.c_str(),
static_cast<char*
>(
nullptr));
2640 std::string out=std::string(
"ABORTED: server=")+mPortName
2641 +std::string(
" alias=")+strAlias
2642 +std::string(
" cmd=stdin\n")
2643 +std::string(
"Can't execute stdin because ")+strerror(error)
2647 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
2648 fprintf(out_to_parent,
"%s", out.c_str());
2649 fflush(out_to_parent);
2650 fclose(out_to_parent);
2651 fprintf(stderr,
"%s", out.c_str());
2659 if (IS_PARENT_OF(pid_stdin))
2664 fprintf(stderr,
"STARTED: server=%s alias=%s cmd=stdin pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdin);
2668 if (IS_INVALID(pid_cmd))
2676 std::string out=std::string(
"ABORTED: server=")+mPortName
2677 +std::string(
" alias=")+strAlias
2678 +std::string(
" cmd=")+strCmd
2679 +std::string(
"\nCan't fork command process because ")+strerror(error)
2684 fprintf(stderr,
"%s", out.c_str());
2686 FILE* to_yarp_stdout=fdopen(pipe_cmd_to_stdout[
WRITE_TO_PIPE],
"w");
2687 fprintf(to_yarp_stdout,
"%s", out.c_str());
2688 fflush(to_yarp_stdout);
2689 fclose(to_yarp_stdout);
2691 SIGNAL(pid_stdout, SIGTERM);
2692 fprintf(stderr,
"TERMINATING stdout (%d)\n", pid_stdout);
2693 SIGNAL(pid_stdin, SIGTERM);
2694 fprintf(stderr,
"TERMINATING stdin (%d)\n", pid_stdin);
2701 if (IS_NEW_PROCESS(pid_cmd))
2705 char *cmd_str=
new char[strCmd.length()+1];
2706 strcpy(cmd_str, strCmd.c_str());
2714 char **arg_str =
new char*[
C_MAXARGS + 1];
2716 arg_str[nargs]=
nullptr;
2718 setvbuf(stdout,
nullptr, _IONBF, 0);
2732 if (msg.
check(
"env"))
2735 for (
const auto& s : ss) {
2736 char* szenv =
new char[s.size()+1];
2737 strcpy(szenv, s.c_str());
2738 yarp::run::impl::putenv(szenv);
2743 if (msg.
check(
"workdir"))
2745 int ret = yarp::os::impl::chdir(msg.
find(
"workdir").
asString().c_str());
2751 std::string out=std::string(
"ABORTED: server=")+mPortName
2752 +std::string(
" alias=")+strAlias
2753 +std::string(
" cmd=")+strCmd
2754 +std::string(
"\nCan't execute command, cannot set working directory ")+strerror(error)
2757 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
2758 fprintf(out_to_parent,
"%s", out.c_str());
2759 fflush(out_to_parent);
2760 fclose(out_to_parent);
2761 fprintf(stderr,
"%s", out.c_str());
2769 char currWorkDirBuff[1024];
2774 char **cwd_arg_str=
new char*[nargs+1];
2775 for (
int i = 1; i < nargs; ++i) {
2776 cwd_arg_str[i] = arg_str[i];
2778 cwd_arg_str[nargs]=
nullptr;
2779 cwd_arg_str[0]=
new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
2781 strcpy(cwd_arg_str[0], currWorkDir);
2782 strcat(cwd_arg_str[0],
"/");
2783 strcat(cwd_arg_str[0], arg_str[0]);
2790 ret = yarp::run::impl::execvp(cwd_arg_str[0], cwd_arg_str);
2792 delete [] cwd_arg_str[0];
2793 delete [] cwd_arg_str;
2803 ret = yarp::run::impl::execvp(arg_str[0], arg_str);
2815 std::string out=std::string(
"ABORTED: server=")+mPortName
2816 +std::string(
" alias=")+strAlias
2817 +std::string(
" cmd=")+strCmd
2818 +std::string(
"\nCan't execute command because ")+strerror(error)
2821 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
2822 fprintf(out_to_parent,
"%s", out.c_str());
2823 fflush(out_to_parent);
2824 fclose(out_to_parent);
2825 fprintf(stderr,
"%s", out.c_str());
2837 if (IS_PARENT_OF(pid_cmd))
2862 if (msg.
check(
"env"))
2867 mProcessVector->Add(pInf);
2871 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
2872 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
2873 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
2883 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
2887 out+=std::string(buff);
2890 fclose(in_from_child);
2899 out=std::string(
"STARTED: server=")+mPortName
2900 +std::string(
" alias=")+strAlias
2901 +std::string(
" cmd=")+strCmd
2910 fprintf(stderr,
"%s", out.c_str());
2920 result.
addString(
"I should never reach this point!!!\n");
2932 std::string portName=
"/log";
2933 portName+=mPortName+
"/";
2935 std::string command = strCmd;
2936 command = command.substr(0, command.find(
' '));
2937 command = command.substr(command.find_last_of(
"\\/") + 1);
2940 if (proc_label !=
"") { portName +=
"[" + proc_label +
"]"; }
2943 int pipe_cmd_to_stdout[2];
2944 int ret_cmd_to_stdout=yarp::run::impl::pipe(pipe_cmd_to_stdout);
2946 int pipe_child_to_parent[2];
2947 int ret_child_to_parent=yarp::run::impl::pipe(pipe_child_to_parent);
2949 if (ret_child_to_parent!=0 || ret_cmd_to_stdout!=0)
2953 std::string out=std::string(
"ABORTED: server=")+mPortName
2954 +std::string(
" alias=")+strAlias
2955 +std::string(
" cmd=stdout\n")
2956 +std::string(
"Can't create pipes ")+strerror(error)
2961 fprintf(stderr,
"%s", out.c_str());
2968 if (IS_INVALID(pid_stdout))
2977 std::string out=std::string(
"ABORTED: server=")+mPortName
2978 +std::string(
" alias=")+strAlias
2979 +std::string(
" cmd=stdout\n")
2980 +std::string(
"Can't fork stdout process because ")+strerror(error)
2985 fprintf(stderr,
"%s", out.c_str());
2990 if (IS_NEW_PROCESS(pid_stdout))
3004 int ret = yarp::run::impl::execlp(
"yarprun",
"yarprun",
"--write", portName.c_str(),
"--log", loggerName.c_str(),
static_cast<char*
>(
nullptr));
3012 std::string out=std::string(
"ABORTED: server=")+mPortName
3013 +std::string(
" alias=")+strAlias
3014 +std::string(
" cmd=stdout\n")
3015 +std::string(
"Can't execute stdout because ")+strerror(error)
3018 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3019 fprintf(out_to_parent,
"%s", out.c_str());
3020 fflush(out_to_parent);
3021 fclose(out_to_parent);
3023 fprintf(stderr,
"%s", out.c_str());
3031 if (IS_PARENT_OF(pid_stdout))
3035 fprintf(stderr,
"STARTED: server=%s alias=%s cmd=stdout pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdout);
3043 if (IS_INVALID(pid_cmd))
3050 std::string out=std::string(
"ABORTED: server=")+mPortName
3051 +std::string(
" alias=")+strAlias
3052 +std::string(
" cmd=")+strCmd
3053 +std::string(
"\nCan't fork command process because ")+strerror(error)
3058 fprintf(stderr,
"%s", out.c_str());
3060 FILE* to_yarp_stdout=fdopen(pipe_cmd_to_stdout[
WRITE_TO_PIPE],
"w");
3061 fprintf(to_yarp_stdout,
"%s", out.c_str());
3062 fflush(to_yarp_stdout);
3063 fclose(to_yarp_stdout);
3065 SIGNAL(pid_stdout, SIGTERM);
3066 fprintf(stderr,
"TERMINATING stdout (%d)\n", pid_stdout);
3072 if (IS_NEW_PROCESS(pid_cmd))
3076 char *cmd_str=
new char[strCmd.length()+1];
3077 strcpy(cmd_str, strCmd.c_str());
3085 char **arg_str =
new char*[
C_MAXARGS + 1];
3087 arg_str[nargs]=
nullptr;
3089 setvbuf(stdout,
nullptr, _IONBF, 0);
3102 if (msg.
check(
"env"))
3105 for (
const auto& s : ss) {
3106 char* szenv =
new char[s.size()+1];
3107 strcpy(szenv, s.c_str());
3108 yarp::run::impl::putenv(szenv);
3113 if (msg.
check(
"workdir"))
3115 int ret = yarp::os::impl::chdir(msg.
find(
"workdir").
asString().c_str());
3121 std::string out=std::string(
"ABORTED: server=")+mPortName
3122 +std::string(
" alias=")+strAlias
3123 +std::string(
" cmd=")+strCmd
3124 +std::string(
"\nCan't execute command, cannot set working directory ")+strerror(error)
3127 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3128 fprintf(out_to_parent,
"%s", out.c_str());
3129 fflush(out_to_parent);
3130 fclose(out_to_parent);
3131 fprintf(stderr,
"%s", out.c_str());
3139 char currWorkDirBuff[1024];
3140 char *currWorkDir=
getcwd(currWorkDirBuff, 1024);
3144 char **cwd_arg_str=
new char*[nargs+1];
3145 for (
int i = 1; i < nargs; ++i) {
3146 cwd_arg_str[i] = arg_str[i];
3148 cwd_arg_str[nargs]=
nullptr;
3149 cwd_arg_str[0]=
new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
3151 strcpy(cwd_arg_str[0], currWorkDir);
3152 strcat(cwd_arg_str[0],
"/");
3153 strcat(cwd_arg_str[0], arg_str[0]);
3160 ret = yarp::run::impl::execvp(cwd_arg_str[0], cwd_arg_str);
3162 delete [] cwd_arg_str[0];
3163 delete [] cwd_arg_str;
3173 ret = yarp::run::impl::execvp(arg_str[0], arg_str);
3184 std::string out=std::string(
"ABORTED: server=")+mPortName
3185 +std::string(
" alias=")+strAlias
3186 +std::string(
" cmd=")+strCmd
3187 +std::string(
"\nCan't execute command because ")+strerror(error)
3190 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3191 fprintf(out_to_parent,
"%s", out.c_str());
3192 fflush(out_to_parent);
3193 fclose(out_to_parent);
3194 fprintf(stderr,
"%s", out.c_str());
3206 if (IS_PARENT_OF(pid_cmd))
3225 if (msg.
check(
"env"))
3230 mProcessVector->Add(pInf);
3234 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
3235 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
3236 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3246 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
3250 out+=std::string(buff);
3253 fclose(in_from_child);
3262 out=std::string(
"STARTED: server=")+mPortName
3263 +std::string(
" alias=")+strAlias
3264 +std::string(
" cmd=")+strCmd
3272 fprintf(stderr,
"%s", out.c_str());
3282 result.
addString(
"I should never reach this point!!!\n");
3294 if (msg.
check(
"forward"))
3296 strCmd=std::string(
"/bin/bash -l -c \"yarprun --readwrite ")+strUUID
3301 strCmd=std::string(
"/bin/bash -l -c \"yarprun --readwrite ")+strUUID+
"\"";
3304 int pipe_child_to_parent[2];
3306 if (yarp::run::impl::pipe(pipe_child_to_parent))
3310 std::string out=std::string(
"ABORTED: server=")+mPortName
3311 +std::string(
" alias=")+strAlias
3312 +std::string(
" cmd=stdio\nCan't create pipe ")+strerror(error)
3318 fprintf(stderr,
"%s", out.c_str());
3325 for (
auto & i : command) {
3329 cmdcpy(command[c++],
"xterm");
3330 cmdcpy(command[c++], msg.
check(
"hold")?
"-hold":
"+hold");
3332 if (msg.
check(
"geometry"))
3334 cmdcpy(command[c++],
"-geometry");
3335 cmdcpy(command[c++], msg.
find(
"geometry").
asString().c_str());
3338 cmdcpy(command[c++],
"-title");
3339 cmdcpy(command[c++], strAlias.c_str());
3341 cmdcpy(command[c++],
"-e");
3342 cmdcpy(command[c++], strCmd.c_str());
3346 if (IS_INVALID(pid_cmd))
3350 std::string out=std::string(
"ABORTED: server=")+mPortName
3351 +std::string(
" alias=")+strAlias
3352 +std::string(
" cmd=stdio\nCan't fork stdout process because ")+strerror(error)
3358 fprintf(stderr,
"%s", out.c_str());
3368 if (IS_NEW_PROCESS(pid_cmd))
3383 int ret = yarp::run::impl::execvp(
"xterm", command);
3391 std::string out=std::string(
"ABORTED: server=")+mPortName
3392 +std::string(
" alias=")+strAlias
3393 +std::string(
" cmd=xterm\nCan't execute command because ")+strerror(error)
3396 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3398 fprintf(out_to_parent,
"%s", out.c_str());
3399 fflush(out_to_parent);
3400 fclose(out_to_parent);
3402 fprintf(stderr,
"%s", out.c_str());
3410 if (IS_PARENT_OF(pid_cmd))
3414 mStdioVector->Add(
new YarpRunProcInfo(strAlias, mPortName, pid_cmd,
nullptr, msg.
check(
"hold")));
3422 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
3423 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
3424 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3433 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
3437 out+=std::string(buff);
3440 fclose(in_from_child);
3446 if (out.substr(0, 14)==
"xterm Xt error" || out.substr(0, 7)==
"ABORTED")
3452 out=std::string(
"STARTED: server=")+mPortName
3453 +std::string(
" alias=")+strAlias
3454 +std::string(
" cmd=xterm pid=")+
int2String(pid_cmd)
3459 fprintf(stderr,
"%s", out.c_str());
3480 int pipe_child_to_parent[2];
3481 int ret_pipe_child_to_parent=yarp::run::impl::pipe(pipe_child_to_parent);
3483 if (ret_pipe_child_to_parent!=0)
3487 std::string out=std::string(
"ABORTED: server=")+mPortName
3488 +std::string(
" alias=")+strAlias
3489 +std::string(
" cmd=stdio\nCan't create pipe ")+strerror(error)
3495 fprintf(stderr,
"%s", out.c_str());
3502 if (IS_INVALID(pid_cmd))
3506 std::string out=std::string(
"ABORTED: server=")+mPortName
3507 +std::string(
" alias=")+strAlias
3508 +std::string(
" cmd=")+strCmd
3509 +std::string(
"\nCan't fork command process because ")+strerror(error)
3514 fprintf(stderr,
"%s", out.c_str());
3519 if (IS_NEW_PROCESS(pid_cmd))
3521 int saved_stderr = yarp::run::impl::dup(STDERR_FILENO);
3522 int null_file=open(
"/dev/null", O_WRONLY);
3529 char *cmd_str=
new char[strCmd.length()+1];
3530 strcpy(cmd_str, strCmd.c_str());
3538 char **arg_str =
new char*[
C_MAXARGS + 1];
3540 arg_str[nargs]=
nullptr;
3550 if (msg.
check(
"env"))
3553 for (
const auto& s : ss) {
3554 char* szenv =
new char[s.size()+1];
3555 strcpy(szenv, s.c_str());
3556 yarp::run::impl::putenv(szenv);
3560 if (msg.
check(
"workdir"))
3562 int ret = yarp::os::impl::chdir(msg.
find(
"workdir").
asString().c_str());
3568 std::string out=std::string(
"ABORTED: server=")+mPortName
3569 +std::string(
" alias=")+strAlias
3570 +std::string(
" cmd=")+strCmd
3571 +std::string(
"\nCan't execute command, cannot set working directory ")+strerror(error)
3574 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3575 fprintf(out_to_parent,
"%s", out.c_str());
3576 fflush(out_to_parent);
3577 fclose(out_to_parent);
3580 fprintf(stderr,
"%s", out.c_str());
3586 char currWorkDirBuff[1024];
3587 char *currWorkDir=
getcwd(currWorkDirBuff, 1024);
3591 char **cwd_arg_str=
new char*[nargs+1];
3592 for (
int i = 1; i < nargs; ++i) {
3593 cwd_arg_str[i] = arg_str[i];
3595 cwd_arg_str[nargs]=
nullptr;
3596 cwd_arg_str[0]=
new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
3599 strcpy(cwd_arg_str[0], currWorkDir);
3600 strcat(cwd_arg_str[0],
"/");
3601 strcat(cwd_arg_str[0], arg_str[0]);
3608 ret = yarp::run::impl::execvp(cwd_arg_str[0], cwd_arg_str);
3610 delete [] cwd_arg_str[0];
3611 delete [] cwd_arg_str;
3620 ret = yarp::run::impl::execvp(arg_str[0], arg_str);
3627 std::string out=std::string(
"ABORTED: server=")+mPortName
3628 +std::string(
" alias=")+strAlias
3629 +std::string(
" cmd=")+strCmd
3630 +std::string(
"\nCan't execute command because ")+strerror(error)
3633 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3634 fprintf(out_to_parent,
"%s", out.c_str());
3635 fflush(out_to_parent);
3636 fclose(out_to_parent);
3638 if (saved_stderr >= 0)
3642 fprintf(stderr,
"%s", out.c_str());
3651 if (IS_PARENT_OF(pid_cmd))
3653 auto* pInf =
new YarpRunProcInfo(strAlias, mPortName, pid_cmd,
nullptr,
false);
3655 if (msg.
check(
"env")) {
3658 mProcessVector->Add(pInf);
3660 sprintf(pidstr,
"%d", pid_cmd);
3664 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
3665 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
3666 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3676 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
3680 out+=std::string(buff);
3683 fclose(in_from_child);
3692 out=std::string(
"STARTED: server=")+mPortName
3693 +std::string(
" alias=")+strAlias
3694 +std::string(
" cmd=")+strCmd
3699 fprintf(stderr,
"%s", out.c_str());
3730 std::string dest_srv=node;
3732 if (command.
check(
"stdio"))
3734 dest_srv=std::string(command.
find(
"stdio").
asString());
3741 if (command.
check(
"geometry"))
3749 if (command.
check(
"hold"))
3768 printf(
":: %s\n", msg.
toString().c_str());
3770 response=sendMsg(msg, dest_srv);
3773 sprintf(buff,
"%d", response.
get(0).
asInt32());
3774 keyv=std::string(buff);
3793 printf(
":: %s\n", msg.
toString().c_str());
3795 response=sendMsg(msg, node);
3813 printf(
":: %s\n", msg.
toString().c_str());
3815 response=sendMsg(msg, node);
3835 printf(
":: %s\n", msg.
toString().c_str());
3837 response=sendMsg(msg, node);
3856 printf(
":: %s\n", msg.
toString().c_str());
3858 response=sendMsg(msg, node);
3860 if (!response.
size()) {
int SIGNAL(int pid, int signum)
std::string int2String(int x)
static yarp::os::Bottle parsePaths(const std::string &txt)
static void sigchld_handler(int sig)
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 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.
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.
yarp::os::SystemInfo::LoadInfo load
current cpu load information
yarp::os::SystemInfo::UserInfo user
current user information
yarp::os::SystemInfo::StorageInfo storage
system storage information
yarp::os::SystemInfo::PlatformInfo platform
operating system information
yarp::os::SystemInfo::MemoryInfo memory
system memory information
yarp::os::SystemInfo::ProcessorInfo processor
system processor type information
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.
std::string send(const std::string &cmd, bool multi=true, const ContactStyle &style=ContactStyle())
Send a text message to the nameserver, and return the result.
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...
std::string toString(const T &value)
convert an arbitrary type to string.
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.
int fork()
Portable wrapper for the fork() 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.
int main(int argc, char *argv[])