wait, waitpid, waitall, and get the shell using them

This commit is contained in:
Lisa Milne 2023-11-26 14:24:37 +10:00
parent 7ac6f677be
commit 39ebcdc049
3 changed files with 134 additions and 16 deletions

View file

@ -173,7 +173,7 @@ Options:
// check if we're on a webserver
if (!remote) {
var u = stdlib.uname();
if (u && u.hostname != 'localhost')
if (u && u.nodename != 'localhost')
remote = true;
}
@ -230,8 +230,10 @@ Options:
pending--;
return;
}
if (!remote && st.type == stdio.types.FT_REMOTE)
if (!remote && st.type == stdio.types.FT_REMOTE) {
pending--;
return;
}
var fd = stdio.open(file,fcb);
if (!fd) {
stdio.write(io.stderr,'cannot open file: '+file);

View file

@ -8,7 +8,7 @@ var clite = {
try{
f();
} catch(e) {
clite.log.write(e.message);
clite.log.write(e.message+':'+e.lineNumber);
return false;
}
return true;
@ -17,7 +17,7 @@ var clite = {
try{
setTimeout(f,10);
} catch(e) {
clite.log.write(e.message);
clite.log.write(e.message+':'+e.lineNumber);
return false;
}
return true;
@ -409,6 +409,7 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`;
// should really have init/getty exec the shell with the env data etc
var env = clite.user.getEnv();
var io = {
pid:0,
stdin:clite.io.open('/dev/tty',false),
stdout:clite.io.open('/dev/tty',false),
stderr:clite.io.open('/dev/tty',false),
@ -433,7 +434,8 @@ clite.proc = {
var vfsapi = vfs;
var data = {
nextid:1,
procs:[]
procs:[],
groups:[]
};
function getProc(pid) {
@ -458,13 +460,58 @@ clite.proc = {
});
return index;
}
function mapCPID(cpid) {
//clite.log.write('mapCPID('+cpid+') -> '+data.groups.length);
if (data.groups.length < 1) {
addGroup(1);
return 1;
}
var parent = getProc(cpid);
if (parent && parent.gpid != cpid)
return parent.gpid;
return cpid;
}
function getGroup(cpid) {
for (var i=0; i<data.groups.length; i++) {
if (data.groups[i].gpid == cpid)
return data.groups[i];
}
return null;
}
function addGroup(cpid) {
if (getGroup(cpid))
return;
data.groups.push({gpid:cpid,waitAny:[],waitAll:[]});
}
function exitGroup(cpid,pid) {
var group = getGroup(cpid);
if (!group)
return false;
group.waitAny.forEach(function(w) {
w(pid);
});
var c = 0;
data.procs.forEach(function(p) {
// we want a count of child processes, so ignore the controlling process
if (p.gpid == cpid && p.pid != cpid)
c++;
});
if (c > 0)
return true;
group.waitAll.forEach(function(w) {
w(pid);
});
return true;
}
clite.proc.add = function(fn) {
clite.proc.add = function(cpid,fn) {
if (typeof fn !== 'function')
return 0;
var proc = Object.create({
gpid:mapCPID(cpid),
pid:data.nextid++,
func:fn
func:fn,
waits:[]
});
data.procs.push(proc);
vfsapi.mkFile('/proc/'+proc.pid);
@ -492,11 +539,56 @@ clite.proc = {
return false;
data.procs.splice(i,1);
vfsapi.remove('/proc/'+pid);
proc.waits.forEach(function(w) {
clite.core.execSafeAsync(function() {w(pid)});
});
exitGroup(proc.gpid,pid);
return true;
}
clite.proc.count = function() {
return data.procs.length;
}
clite.proc.addWait = function(pid,w) {
var proc = getProc(pid);
if (!proc) {
clite.core.execSafeAsync(function() {w(pid)});
return false;
}
proc.waits.push(w);
return true;
}
clite.proc.addWaitGroupAny = function(pid,w) {
var cpid = mapCPID(pid);
var group = getGroup(cpid);
if (!group) {
clite.core.execSafeAsync(function() {w(pid)});
return true;
}
group.waitAny.push(w);
return true;
}
clite.proc.addWaitGroupAll = function(pid,w) {
var cpid = mapCPID(pid);
var group = getGroup(cpid);
if (!group) {
clite.core.execSafeAsync(function() {w(pid)});
return false;
}
group.waitAll.push(w);
return true;
}
clite.proc.addGroup = function(pid) {
var proc = getProc(pid);
if (!proc)
return false;
if (proc.gpid == pid)
return true;
proc.gpid = pid;
if (getGroup(pid))
return true;
addGroup(pid);
return true;
}
clite.proc.init = null;
return true;
},
@ -1273,12 +1365,6 @@ clite.term = {
return;
f.parentNode.removeChild(f);
},
hasInput:function() {
var f = document.getElementById('form');
if (!f)
return false;
return true;
},
writeLine:function(txt) {
var a = document.createElement('article');
a.innerHTML = clite.lib.htmlEncode(txt);
@ -1286,6 +1372,8 @@ clite.term = {
if (!t)
return;
t.appendChild(a);
if (document.getElementById('form'))
clite.term.genForm();
t.scrollTop = t.scrollHeight;
},
genForm:function() {
@ -1640,10 +1728,11 @@ clite.lib = {
return o;
},
fork:function(env,io,call) {
var pid = clite.proc.add(call);
var pid = clite.proc.add(io.pid,call);
if (!pid)
return 0;
var nio = Object.create(io);
nio.pid = pid;
nio.exit = function(v) {
clite.lib.exit(pid,v);
try{
@ -1653,7 +1742,17 @@ clite.lib = {
nio.include = function(name) {
switch (name) {
case 'stdlib':
return Object.create(clite.lib.api);
var stdlib = Object.create(clite.lib.api);
stdlib.wait = function(cb) {
return clite.lib.wait(nio.pid,cb);
}
stdlib.waitpid = function(pid,cb) {
return clite.lib.waitpid(nio.pid,pid,cb);
}
stdlib.waitall = function(cb) {
return clite.lib.waitall(nio.pid,cb);
}
return stdlib;
break;
case 'stdio':
var stdio = Object.create(clite.io);
@ -1707,6 +1806,20 @@ clite.lib = {
},
getgid:function() {
return clite.user.getGID();
},
// wait for any child process to exit
wait:function(cpid,cb) {
return clite.proc.addWaitGroupAny(cpid,cb);
},
// wait for the process 'pid' to exit
waitpid:function(cpid,pid,cb) {
if (pid < 0)
return clite.lib.wait(cpid,cb);
return clite.proc.addWait(pid,cb);
},
// wait for all child processes to exit
waitall:function(cpid,cb) {
return clite.proc.addWaitGroupAll(cpid,cb);
}
}
clite.lib.api = { // this is passed to programs via include('stdlib')

View file

@ -188,6 +188,7 @@ clite.commands.load('sh',function(args,env,io) {
// prepare io (stdin,stdout,stderr)
// TODO: check for io redirects and piping, then setup stdio accordingly
var fio = {
pid:io.pid,
stdin:io.stdin,
stdout:io.stdout,
stderr:io.stderr,
@ -303,7 +304,9 @@ clite.commands.load('sh',function(args,env,io) {
}
}
inputRead();
// TODO: something something waitall()
stdlib.waitall(inputRead);
//inputRead();
return null;
});