drive program

jruby は pid をなかなか正しく返してくれない... $$ も Process.pid も, 1.1rc2 でもだ。

javaAPI には pid をえる標準的なものは見当たらない。

Groovy はプロセスに相当するようなものを別に持っているとは思えない。

jython もすこし頭をよぎったが、動かすことが先決、ということで C++ だ。


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

class tcfg {
public:
string java;
string opts;
string cls;

tcfg(string j, string o, string c) : java(j), opts(o), cls(c) { }
};

#define JAVA_PATH "/usr/java/bin/java"

tcfg tcfgs[] = {
tcfg(JAVA_PATH, "-XX:+PrintClassHistogram -XX:+UseSerialGC", "Test"),
tcfg(JAVA_PATH, "-XX:+PrintClassHistogram -XX:+UseConcMarkSweepGC", "Test"),
tcfg(JAVA_PATH, "-XX:+PrintClassHistogram -XX:+UseParallelGC", "Test"),
};

string memopts = "-Xmx24m -XX:MaxPermSize=4m -XX:ReservedCodeCacheSize=8m";

static vector split(const string &st, const string& sep) {
// record separator position
vector sp;
sp.push_back(0);
string::size_type pos;
int index = 0, st_len = st.length();
int sep_len = sep.length();

while ((pos = st.find(sep, index)) != string::npos) {
index = pos + sep_len;
sp.push_back(index);
if (index >= st_len) break;
}

vector sl;
for (int i = 0; i < sp.size(); i++) {
if ((i+1) == sp.size()) { // special case for last index
sl.push_back(st.substr(sp[i], st.length()-sp[i]));
continue; // can be break
}
sl.push_back(st.substr(sp[i], sp[i+1]-sp[i]-sep_len));
}

return sl;
}

void doit(tcfg& cfg) {
pid_t cpid = fork();

if (cpid == 0) {
vector mopts = split(memopts, " "); //2
vector opts = split(cfg.opts, " "); //3
char **args = new char*[mopts.size() + opts.size() + 3]; // 8

//args[0] = "java";
args[0] = const_cast(cfg.java.c_str());

int off = 1; // 1
for (int i = 0; i < mopts.size(); i++) {
args[i+off] = const_cast(mopts[i].c_str());
}
off += mopts.size(); // 3
for (int i = 0; i < opts.size(); i++) {
args[i+off] = const_cast(opts[i].c_str());
}
off += opts.size(); // 6
args[off] = const_cast(cfg.cls.c_str());
off += 1;
args[off] = 0;

cout << "a: ";
for (int i = 0; i <= off; i++) {
cout << args[i] << " ";
}
cout << endl;

pid_t pid = getpid();
stringstream ss;
ss << "out." << dec << pid;
string ofn = ss.str();

stringstream sse;
sse << "err." << dec << pid;
string efn = sse.str();

close(1);
open(ofn.c_str(), O_RDWR|O_CREAT, 0644);
close(2);
open(efn.c_str(), O_RDWR|O_CREAT, 0644);

int r = execv(cfg.java.c_str(), args);

if (r) {
cout << "exec error: " << strerror(errno) << endl;
}

} else if (cpid > 0) {
cout << "child pid " << dec << cpid << endl;
sleep(10);
cout << "parent sending signal 3" << endl;
int r = kill(cpid, SIGQUIT);
sleep(5);

cout << "parent sending signal 2" << endl;
r = kill(cpid, SIGINT);
cout << "parent sending signal 15" << endl;
r = kill(cpid, SIGTERM);

int wstat;
pid_t wr = waitpid(cpid, &wstat, 0);

cout << "wait returned for " << wr << endl;

struct stat statbuf;

r = stat("core", &statbuf);

if (r == 0) {
stringstream ss;
ss << "core." << dec << cpid;
string cfn = ss.str();
r = rename("core", cfn.c_str());
cout << "core found. renamed to " << cfn << endl;
}
} else {
cout << "fork error: " << strerror(errno) << endl;
}
}

void setupSig()
{
struct sigaction act;

memset(&act, 0, sizeof(act));

act.sa_handler = SIG_IGN;
act.sa_flags = SA_NOCLDWAIT;
int r = sigaction(SIGCHLD, &act, 0);
if (r < 0) {
cout << "sigaction error: " << strerror(errno) << endl;
exit(errno);
}

}

int main(int argc, char *argv[])
{
setupSig();
for (int i = 0; i < sizeof(tcfgs)/sizeof(tcfg); i++) {
//cout << tcfgs[i].java << " " << tcfgs[i].opts << endl;
doit(tcfgs[i]);
}
return 0;
}