]> git.tdb.fi Git - libs/core.git/blob - source/core/unix/process.cpp
Add move semantics to Variant
[libs/core.git] / source / core / unix / process.cpp
1 #include <unistd.h>
2 #include <sys/wait.h>
3 #include <signal.h>
4 #include <msp/core/systemerror.h>
5 #include <msp/fs/dir.h>
6 #include <msp/io/console.h>
7 #include "except.h"
8 #include "process.h"
9 #include "process_private.h"
10
11 using namespace std;
12
13 namespace Msp {
14
15 Process::~Process()
16 {
17         delete priv;
18 }
19
20 void Process::platform_get_self_info(Private &priv)
21 {
22         priv.info.pid = getpid();
23 }
24
25 void Process::execute(const string &command, bool path_search, const Arguments &args)
26 {
27         pid_t pid = 0;
28         if(this!=_self)
29                 pid = fork();
30
31         if(pid==-1)
32                 throw system_error("fork");
33         else if(pid==0)
34         {
35                 try
36                 {
37                         vector<const char *> argv(args.size()+2);
38                         argv[0] = command.c_str();
39                         for(unsigned i=0; i<args.size(); ++i)
40                                 argv[i+1] = args[i].c_str();
41                         argv[args.size()+1] = nullptr;
42
43                         if(redirect)
44                         {
45                                 // dup2 clears O_CLOEXEC
46                                 if(cin)
47                                         IO::cin.redirect(*cin);
48                                 if(cout)
49                                         IO::cout.redirect(*cout);
50                                 if(cerr)
51                                         IO::cerr.redirect(*cerr);
52                         }
53
54                         if(!work_dir.empty())
55                                 FS::chdir(work_dir);
56
57                         if(path_search)
58                                 execvp(command.c_str(), const_cast<char *const *>(&argv[0]));
59                         else
60                                 execv(command.c_str(), const_cast<char *const *>(&argv[0]));
61                 }
62                 catch(...)
63                 { }
64                 _exit(255);
65         }
66         else
67         {
68                 priv->info.pid = pid;
69                 running = true;
70         }
71 }
72
73 bool Process::wait(bool block)
74 {
75         if(!running)
76                 throw invalid_state("not running");
77
78         int status;
79         int pid = waitpid(priv->info.pid, &status, (block ? 0 : WNOHANG));
80         if(pid==-1)
81                 throw system_error("waitpid");
82
83         if(pid)
84         {
85                 finished = true;
86                 running = false;
87                 if(WIFEXITED(status))
88                         exit_code = WEXITSTATUS(status);
89                 else if(WIFSIGNALED(status))
90                         exit_code = 0x100|WTERMSIG(status);
91         }
92
93         return finished;
94 }
95
96 void Process::terminate()
97 {
98         ::kill(priv->info.pid, SIGTERM);
99 }
100
101 void Process::kill()
102 {
103         ::kill(priv->info.pid, SIGKILL);
104 }
105
106 void Process::interrupt()
107 {
108         ::kill(priv->info.pid, SIGINT);
109 }
110
111
112 Process::Private::Private()
113 {
114         info.pid = 0;
115 }
116
117 } // namespace Msp