00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdio.h>
00025 #include <unistd.h>
00026 #include <stdlib.h>
00027 #include <signal.h>
00028 #include <sys/types.h>
00029 #include <sys/wait.h>
00030
00031 #include <stlib/os/Process.h>
00032 #include <stlib/Array.h>
00033 #include <stlib/FileAccessor.h>
00034 #include <stlib/Iterator.h>
00035 #include <stlib/Set.h>
00036 #include <stlib/String.h>
00037
00038 using namespace OS;
00039
00040 bool Process::has_handler = false;
00041 Set Process::processes(5);
00042
00043 Process::Process(void)
00044 {
00045 finalizeProcesses();
00046 _receiver = nil;
00047 _arguments = nil;
00048
00049 runningProcess = false;
00050 process_id = 0;
00051 _status = 0;
00052 }
00053
00054 Process::Process(Callback<void> *receiver, Array *args)
00055 {
00056 finalizeProcesses();
00057
00058 _receiver = receiver;
00059 _arguments = args;
00060
00061 runningProcess = false;
00062 process_id = 0;
00063 _status = 0;
00064 }
00065
00066 Process::~Process(void)
00067 {
00068
00069 }
00070
00071 Process *Process::fork(Callback<void> *receiver)
00072 {
00073 Process *process = new Process(receiver);
00074 process->run();
00075 return process;
00076 }
00077
00078 Process *Process::fork(Callback<void> *receiver, Array *args)
00079 {
00080 Process *process = new Process(receiver, args);
00081 process->run();
00082 return process;
00083 }
00084
00085 Process *Process::forkJob(String *progName, SequenceableCollection *args,
00086 SequenceableCollection *fds)
00087 {
00088 Callback1<Process,void,Array*> *callback;
00089 Array *funcArgs = Array::with(progName, args, fds);
00090 Process *process = new Process;
00091
00092 callback = new Callback1<Process,void,Array*>(process, &Process::privateExecuteJob);
00093 process->receiver(callback);
00094 process->arguments(funcArgs);
00095 process->run();
00096 return process;
00097 }
00098
00099
00100 void Process::arguments(Array *args)
00101 {
00102 _arguments = args;
00103 }
00104
00105 void Process::receiver(Callback<void> *obj)
00106 {
00107 _receiver = obj;
00108 }
00109
00110 int Process::status(void)
00111 {
00112 return _status;
00113 }
00114
00115
00116 void Process::finalizeProcesses(void)
00117 {
00118 Set *temp = (Set *) processes.copy();
00119 for (Iterator* i = temp->iterator(); !i->finished(); i->next()) {
00120 Process *p = (Process *) i->value();
00121 if (!p->isRunning())
00122 p->finalize();
00123 }
00124 delete temp;
00125 }
00126
00127
00128 void Process::resume()
00129 {
00130 if (runningProcess == false) {
00131
00132 return;
00133 }
00134 kill(process_id, SIGCONT);
00135 }
00136
00137
00138 void Process::suspend()
00139 {
00140 if (runningProcess == false) {
00141
00142 return;
00143 }
00144 kill(process_id, SIGSTOP);
00145 }
00146
00147 void Process::run()
00148 {
00149 int pid;
00150 if (_receiver == nil) return;
00151
00152 if ((pid = ::fork()) == 0) {
00153
00154 runningProcess = true;
00155 _receiver->executeWith(_arguments);
00156 exit(0);
00157 } else {
00158
00159 if (pid == -1) {
00160
00161 return;
00162 }
00163 runningProcess = true;
00164 process_id = pid;
00165 processes.add(this);
00166 if (!has_handler) {
00167 struct sigaction handler;
00168 handler.sa_handler = Process::sigchildHandler;
00169 handler.sa_flags = SA_NOCLDSTOP;
00170 sigaction(SIGCHLD, &handler, NULL);
00171 has_handler = true;
00172 }
00173 }
00174 }
00175
00176 void Process::finalize(void)
00177 {
00178 processes.remove(this);
00179 }
00180
00181 void Process::terminate(void)
00182 {
00183
00184 if (runningProcess != false) {
00185 kill(process_id, SIGTERM);
00186
00187 finalize();
00188 }
00189 }
00190
00191 void Process::yield(void)
00192 {
00193
00194
00195 }
00196
00197
00198 bool Process::isRunning(void)
00199 {
00200 return runningProcess;
00201 }
00202
00203
00204 void Process::childSignaled(void)
00205 {
00206 int pid;
00207 pid = waitpid(process_id, &_status, WNOHANG);
00208 if (pid > 0) {
00209 runningProcess = false;
00210 finalize();
00211 }
00212 }
00213
00214 void Process::privateExecuteJob(Array *args)
00215 {
00216 String *progName = (String *) args->at(0);
00217 SequenceableCollection *progArgs = (SequenceableCollection *) args->at(1);
00218 SequenceableCollection *fds = (SequenceableCollection *) args->at(2);
00219
00220 char *file = progName->asCString();
00221 char *fileArgs[progArgs->size() + 2];
00222 fileArgs[0] = file;
00223 for (int i = 0; i < progArgs->size(); i++)
00224 fileArgs[i+1] = dynamic_cast<String *>(progArgs->at(i))->asCString();
00225 fileArgs[progArgs->size() + 1] = NULL;
00226
00227 if (fds != nil) {
00228 FileAccessor *fd = dynamic_cast<FileAccessor *>(fds->at(0));
00229 if (fd != nil) {
00230 close(0);
00231 fd->changeDescriptorTo(0);
00232 }
00233 fd = dynamic_cast<FileAccessor *>(fds->at(1));
00234 if (fd != nil) {
00235 close(1);
00236 fd->changeDescriptorTo(1);
00237 }
00238 fd = dynamic_cast<FileAccessor *>(fds->at(2));
00239 if (fd != nil) {
00240 close(2);
00241 fd->changeDescriptorTo(2);
00242 }
00243 }
00244 execvp(file, fileArgs);
00245 }
00246
00247 void Process::sigchildHandler(int signum)
00248 {
00249 Set *temp = (Set *) processes.copy();
00250 for (Iterator* i = temp->iterator(); !i->finished(); i->next()) {
00251 Process *p = (Process *) i->value();
00252 p->childSignaled();
00253 }
00254 delete temp;
00255 }