36 #include "ns3/simulator.h"
37 #include "ns3/ipv4-address.h"
38 #include "ns3/packet.h"
40 #include "ns3/uinteger.h"
41 #include "ns3/boolean.h"
42 #include "ns3/trace-source-accessor.h"
52 #include <arpa/inet.h>
53 #include <sys/types.h>
72 static TypeId tid = TypeId (
"ns3::DceManager")
74 .AddConstructor<DceManager> ()
75 .AddTraceSource (
"Exit",
"A process has exited",
77 .AddAttribute (
"FirstPid",
"The PID used by default when creating a process in this manager.",
80 MakeUintegerChecker<uint16_t> ())
81 .AddAttribute (
"MinimizeOpenFiles",
"For each DCE virtual process running it exists 3 files opened (stdin,stdout and stderr),"
82 " if you enable this flag, the 2 files stderr and stdout will be closed between each write in order to "
83 " minimize the number of opened files and then maximize the number of DCE virtual process running at the same time.",
86 MakeBooleanChecker ())
93 NS_LOG_FUNCTION (
this);
97 NS_LOG_FUNCTION (
this);
102 NS_LOG_FUNCTION (
this);
104 std::map<uint16_t, Process*> mapCopy =
m_processes;
107 for (std::map<uint16_t, Process*>::iterator it = mapCopy.begin (); it != mapCopy.end (); it++)
110 std::string statusWord =
"Never ended.";
121 static struct ::Libc *libc = 0;
133 int fd =
dce_open (dirName.c_str (), O_DIRECTORY | O_RDONLY, 0);
138 else if (current->
err == ENOENT)
140 int status =
dce_mkdir (dirName.c_str (), S_IRWXU | S_IRWXG);
143 NS_FATAL_ERROR (
"Could not create directory " << dirName
144 <<
": " << strerror (current->
err));
149 NS_FATAL_ERROR (
"Could not open \"" << dirName <<
"\"");
158 std::ostringstream oss;
160 std::string pidDirName = oss.str ();
162 oss <<
"/" << filename;
163 std::string s = oss.str ();
164 int fd =
dce_creat (s.c_str (), S_IWUSR | S_IRUSR);
174 int (*
main)(int,
char **) = 0;
178 if (current->process->stdinFilename.length () > 0)
181 int realFd = ::open (fullpath.c_str (), O_RDONLY, 0);
185 NS_FATAL_ERROR (
"Unable to open stdin file : " << current->process->stdinFilename);
187 unixFd =
new UnixFileFd (realFd);
191 unixFd =
new TermUnixFileFd (0);
195 current->process->openFiles[0] =
new FileUsage (0, unixFd);
198 int fd = CreatePidFile (current,
"stdout");
201 fd = CreatePidFile (current,
"stderr");
204 fd = CreatePidFile (current,
"cmdline");
206 for (
int i = 0; i < current->process->originalArgc; i++)
208 char *cur = current->process->originalArgv[i];
211 current->process->timing.cmdLine += cur;
212 if (i < (current->process->originalArgc - 1))
214 current->process->timing.cmdLine +=
' ';
220 fd = CreatePidFile (current,
"status");
223 std::ostringstream oss;
225 std::string tmp = oss.str ();
226 const char *str = tmp.c_str ();
230 std::string vpath =
"";
231 char *pvpath =
seek_env (
"PATH", current->process->originalEnvp);
234 vpath = std::string (pvpath);
237 std::string exeFullPath =
SearchExecFile (current->process->originalArgv[0], vpath, getuid (), getgid (), &errNo);
239 if (exeFullPath.length () <= 0)
241 std::string line =
"Executable '";
242 line += current->process->originalArgv[0];
243 line +=
"' not found ! Please check your DCE_PATH and DCE_ROOT environment variables.";
244 AppendStatusFile (current->process->pid, current->process->nodeId, line);
245 NS_ASSERT_MSG (exeFullPath.length () > 0, line.c_str ());
250 main = (int (*) (int,
char **))LoadMain (current->process->loader,
257 std::string line =
"No main method found in executable file '";
260 AppendStatusFile (current->process->pid, current->process->nodeId, line);
261 NS_ASSERT_MSG (!
main, line.c_str ());
265 std::string line =
"Starting: " + exeFullPath;
266 AppendStatusFile (current->process->pid, current->process->nodeId, line);
293 std::vector<std::pair<std::string,std::string> > envs,
int pid)
308 Ptr<LoaderFactory> loaderFactory = this->GetObject<LoaderFactory> ();
318 process->
name = name;
346 process->
uMask = 022;
351 process->
rndVarible = UniformVariable (0, RAND_MAX);
381 std::vector<std::pair<std::string,std::string> > envs,
382 uid_t uid, uid_t euid, uid_t gid, uid_t egid)
384 NS_LOG_FUNCTION (
this << name << args.size ());
387 process->
euid = euid;
389 process->
egid = egid;
399 std::vector<std::string> args,
400 std::vector<std::pair<std::string,std::string> > envs,
401 uid_t uid, uid_t euid, uid_t gid, uid_t egid)
403 NS_LOG_FUNCTION (
this << name << stackSize << args.size () << envs.size ());
406 process->
euid = euid;
408 process->
egid = egid;
419 std::vector<std::string> nullargs;
420 std::vector<std::pair<std::string,std::string> > nullenvs;
430 std::vector<std::string> nullargs;
431 std::vector<std::pair<std::string,std::string> > envs;
464 NS_LOG_FUNCTION (
this);
480 NS_LOG_FUNCTION (
this);
481 for (uint16_t i = 0; i < 0xffff; i++)
483 uint16_t candidatePid = (
m_nextPid + i) & 0xffff;
490 NS_FATAL_ERROR (
"Too many processes");
496 for (uint16_t tid = 0; tid < 0xffff; tid++)
499 for (std::vector<struct Thread *>::const_iterator i = process->
threads.begin (); i != process->
threads.end (); ++i)
513 NS_FATAL_ERROR (
"We attempted to allocate a new tid for this process but none were available: "
514 "too many threads created at the same time.");
521 NS_LOG_FUNCTION (
this << process);
523 NS_LOG_DEBUG (
"Create " << thread);
535 if (!process->
threads.empty ())
541 for (std::list<struct ThreadKeyValue>::iterator i = thread->
keyValues.begin ();
547 process->
threads.push_back (thread);
571 for (std::vector<Thread *>::const_iterator j = process->
threads.begin ();
572 j != process->
threads.end (); ++j)
587 NS_LOG_FUNCTION (
this << thread);
610 for (std::map <int, FileUsage*>::iterator i = thread->
process->
openFiles.begin ();
640 clone->
rndVarible = UniformVariable (0, RAND_MAX);
652 cloneThread->
task = task;
697 NS_LOG_FUNCTION (
this << pid);
704 std::string statusWord =
"Stopped by NS3.";
711 NS_ASSERT (signal == SIGKILL);
717 NS_ASSERT (signal == SIGABRT);
723 if (thread->
ioWait.first != 0 && thread->
ioWait.second != 0)
725 thread->
ioWait.first->RemoveWaitQueue (thread->
ioWait.second,
false);
726 if (thread->
ioWait.second)
728 delete thread->
ioWait.second;
745 NS_LOG_FUNCTION (
this << thread);
746 if (thread->
task != 0)
750 GetObject<TaskManager> ()->
Stop (thread->
task);
753 for (std::vector<Thread *>::iterator i = thread->
process->
threads.begin ();
774 NS_LOG_FUNCTION (
this << process <<
"pid" << std::dec << process->
pid <<
"ppid" << process->
ppid);
778 std::vector<Thread *> threads = process->
threads;
781 while (!threads.empty ())
783 tmp = threads.back ();
792 std::map<int,FileUsage *> openFiles = process->
openFiles;
794 for (std::map <int, FileUsage*>::iterator i = openFiles.begin ();
795 i != openFiles.end (); ++i)
812 for (uint32_t i = 0; i < process->
openStreams.size (); i++)
825 for (uint32_t i = 0; i < process->
openDirs.size (); i++)
836 process->
itimer.Cancel ();
838 std::map<int,FileUsage *> openFiles = process->
openFiles;
840 for (std::map <int, FileUsage*>::iterator i = openFiles.begin ();
841 i != openFiles.end (); ++i)
853 while (!process->
threads.empty ())
855 tmp = process->
threads.back ();
860 for (uint32_t i = 0; i < process->
mutexes.size (); ++i)
869 for (uint32_t i = 0; i < process->
semaphores.size (); ++i)
879 void *buffer = process->
allocated.back ();
884 int ppid = process->
ppid;
889 std::set<uint16_t> children = process->
children;
891 std::set<uint16_t>::iterator it;
893 for (it = children.begin (); it != children.end (); it++)
916 delete process->
alloc;
951 NS_LOG_FUNCTION (
this << pid << tid);
958 for (std::vector<Thread *>::const_iterator j = process->
threads.begin ();
959 j != process->
threads.end (); ++j)
962 if (thread->
tid == tid)
972 NS_LOG_FUNCTION (
this << pid);
974 std::map<uint16_t, Process *>::iterator it =
m_processes.find (pid);
987 int argc = args.size () + 1;
988 char **argv = (
char **)malloc (
sizeof (
char *) * (argc + 1));
990 argv[0] = strdup (filename.c_str ());
992 for (uint32_t i = 0; i < args.size (); ++i)
994 char *arg = strdup (args[i].c_str ());
995 NS_LOG_DEBUG (
"argc=" << argc <<
" i=" << i <<
" v=" << arg);
1007 std::vector<std::pair<std::string,std::string> > envs)
1009 int envpc = envs.size ();
1010 char **envp = (
char **)malloc (
sizeof (
char *) * (envpc + 1));
1012 for (uint32_t i = 0; i < envs.size (); ++i)
1014 int size = envs[i].first.size () + envs[i].second.size () + 1;
1015 envp[i] = (
char*)malloc (size + 1);
1017 memcpy (envp[i], envs[i].first.c_str (), envs[i].first.size ());
1018 envp[i][envs[i].first.size ()] =
'=';
1019 memcpy (envp[i] + envs[i].first.size () + 1, envs[i].second.c_str (), envs[i].second.size ());
1021 NS_LOG_DEBUG (
"envpc=" << envpc <<
" i=" << i <<
" v=" << envp[i]);
1030 std::ostringstream oss;
1031 oss <<
"files-" << nodeId <<
"/var/log/" << pid <<
"/status";
1032 std::string s = oss.str ();
1034 int fd = ::open (s.c_str (), O_WRONLY | O_APPEND, 0);
1040 oss <<
" Time: " <<
GetTimeStamp () <<
" --> " << line << std::endl;
1041 std::string wholeLine = oss.str ();
1042 int l = wholeLine.length ();
1043 const char *str = wholeLine.c_str ();
1044 ::write (fd, str, l);
1055 std::ostringstream oss;
1056 int fd = ::open (
"exitprocs", O_WRONLY | O_APPEND | O_CREAT, 0644);
1061 if ((!fstat (fd, &st)) && (0 == st.st_size))
1063 const char *header =
"NODE EXIT-CODE PID NS3-START-TIME NS3-END-TIME REAL-START-TIME REAL-END-TIME NS3-DURATION REAL-DURATION CMDLINE\n";
1065 ::write (fd, header, strlen (header));
1078 std::string wholeLine = oss.str ();
1079 int l = wholeLine.length ();
1080 const char *str = wholeLine.c_str ();
1081 ::write (fd, str, l);
1086 std::map<uint16_t, Process *>
1103 std::set<uint16_t>::iterator it = p->
children.find (pid);
1116 std::vector<Thread *> tt = p->
threads;
1118 for (std::vector<Thread*>::iterator it = tt.begin (); it != tt.end (); it++)
1140 std::vector<std::string>
1143 std::vector<std::string> args;
1148 char **v = (
char **) argv;
1166 char **e = (
char **) envp;
1173 while ((*c != 0) && (*c !=
'='))
1178 if ((
'=' != *c) || (s == c))
1183 std::string key = std::string (s, c);
1184 std::string val = std::string (1 + c);
1185 envs.push_back (std::make_pair (key, val));
1194 void *h = ld->
Load (
"libc-ns3.so", RTLD_GLOBAL);
1196 struct ::Libc *libc =
GetLibc ();
1205 symbol = ld->
Lookup (h,
"libc_setup");
1208 NS_FATAL_ERROR (
"This is not our fake libc !");
1211 void (*libc_setup)(
const struct Libc *fn);
1212 libc_setup = (void (*) (
const struct Libc *))(symbol);
1215 h = ld->
Load (
"libpthread-ns3.so", RTLD_GLOBAL);
1223 symbol = ld->
Lookup (h,
"libpthread_setup");
1226 NS_FATAL_ERROR (
"This is not our fake libpthread !");
1229 void (*libpthread_setup)(
const struct Libc *fn);
1230 libpthread_setup = (void (*) (
const struct Libc *))(symbol);
1231 libpthread_setup (libc);
1233 h = ld->
Load (
"librt-ns3.so", RTLD_GLOBAL);
1239 symbol = ld->
Lookup (h,
"librt_setup");
1242 NS_FATAL_ERROR (
"This is not our fake librt !");
1245 void (*librt_setup)(
const struct Libc *fn);
1246 librt_setup = (void (*) (
const struct Libc *))(symbol);
1249 h = ld->
Load (
"libm-ns3.so", RTLD_GLOBAL);
1255 symbol = ld->
Lookup (h,
"libm_setup");
1258 NS_FATAL_ERROR (
"This is not our fake libm !");
1261 void (*libm_setup)(
const struct Libc *fn);
1262 libm_setup = (void (*) (
const struct Libc *))(symbol);
1266 h = ld->
Load (filename, RTLD_GLOBAL);
1276 symbol = ld->
Lookup (h,
"main");
1277 err = (0 != symbol) ? 0 : ENOEXEC;
1286 int (*
main)(int,
char **) = (
int (*) (int,
char **))c;
1299 handler.
signal = SIGKILL;
1301 sigemptyset (&handler.
mask);
1303 signalHandlers.push_back (handler);
1306 handler.
signal = SIGABRT;
1308 sigemptyset (&handler.
mask);
1310 signalHandlers.push_back (handler);
1317 std::vector<std::pair<std::string,std::string> > envs;
1318 memset (&pTemp, 0,
sizeof (
Process));
1325 std::ostringstream interpreter, optArgs;
1326 std::string filename = std::string (path);
1329 std::vector<std::string> args, lasts =
CopyArgs (argv);
1330 std::string opt = optArgs.str ();
1331 std::string shell = interpreter.str ();
1333 if (opt.length () > 0)
1335 args.push_back (opt);
1337 args.push_back (argv0);
1339 if (lasts.size () > 0)
1341 args.insert (args.end (), lasts.begin (), lasts.end ());
1344 SetArgv (&pTemp, argv0, args);
1346 std::string vpath =
"";
1350 vpath = std::string (pvpath);
1353 if (filename.length () <= 0)
1365 std::ostringstream oss;
1371 std::string line = oss.str ();
1375 Ptr<LoaderFactory> loaderFactory = this->GetObject<LoaderFactory> ();
1380 FILE **pstdin = process->
pstdin;
1381 FILE **pstdout = process->
pstdout;
1382 FILE **pstderr = process->
pstderr;
1383 char ***penvp = process->
penvp;
1386 std::vector<FILE *> openStreams = process->
openStreams;
1398 process->
pstdin = pstdin;
1401 process->
penvp = penvp;
1414 line =
"EXEC FAILED";
1419 while (!openStreams.empty ())
1421 FILE *f = openStreams.back ();
1422 openStreams.pop_back ();
1430 std::vector<Thread *> Oldthreads = process->
threads;
1439 thread->
task = task;
1447 void *buffer = process->
allocated.back ();
1458 process->
name = std::string (path);
1467 std::vector<Thread *> threads = Oldthreads;
1470 while (!threads.empty ())
1472 tmp = threads.back ();
1473 threads.pop_back ();
1478 threads = Oldthreads;
1480 while (!threads.empty ())
1482 tmp = threads.back ();
1483 threads.pop_back ();
1487 Oldthreads.clear ();
1489 delete process->
alloc;
1492 while (!process->
mutexes.empty ())
1522 line =
"EXEC SUCCESS";