A-M baby
This commit is contained in:
parent
764da6cbbb
commit
db842d013d
19005 changed files with 197040 additions and 7 deletions
2
Task/Fork/Fexl/fork-1.fexl
Normal file
2
Task/Fork/Fexl/fork-1.fexl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fork \pid
|
||||
print "pid = ";print pid;nl;
|
||||
87
Task/Fork/Fexl/fork-2.fexl
Normal file
87
Task/Fork/Fexl/fork-2.fexl
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
# (spawn child_fn next)
|
||||
# Fork the child function as a process and return its pid, stdin, stdout, and
|
||||
# stderr.
|
||||
\spawn =
|
||||
(
|
||||
### Use error-checking versions of system routines
|
||||
\pipe =
|
||||
(\next
|
||||
pipe \status\read\write
|
||||
long_lt status 0 (die "pipe failed");
|
||||
next read write
|
||||
)
|
||||
|
||||
\dup2 =
|
||||
(\oldfd\newfd\next
|
||||
dup2 oldfd newfd \status
|
||||
long_lt status 0 (die "dup2 failed");
|
||||
next
|
||||
)
|
||||
|
||||
\fdopen =
|
||||
(\fd\mode\next
|
||||
fdopen fd mode next;
|
||||
die "fdopen failed"
|
||||
)
|
||||
|
||||
\fork =
|
||||
(\next
|
||||
fork \pid
|
||||
long_lt pid 0 (die "fork failed");
|
||||
next pid
|
||||
)
|
||||
|
||||
# Now here's the spawn function itself.
|
||||
\child_fn\next
|
||||
|
||||
# First flush the parent's stdout and stderr to avoid any pending output
|
||||
# accidentally getting pushed into the child's input. I've noticed this
|
||||
# can happen when your script output is sent to a file or pipe instead of
|
||||
# a console.
|
||||
get_stdout \fh fflush fh \_
|
||||
get_stderr \fh fflush fh \_
|
||||
|
||||
# Now create a series of pipes, each with a read and write side.
|
||||
pipe \r_in\w_in
|
||||
pipe \r_out\w_out
|
||||
pipe \r_err\w_err
|
||||
|
||||
fork \pid
|
||||
long_eq pid 0
|
||||
(
|
||||
# Child process.
|
||||
|
||||
# Duplicate one side of each pipe into stdin, stdout, and stderr
|
||||
# as appropriate.
|
||||
dup2 r_in 0;
|
||||
dup2 w_out 1;
|
||||
dup2 w_err 2;
|
||||
|
||||
# Close unused file handles. They're all unused because we duped the
|
||||
# ones we need. Also, we must close w_in or the child hangs waiting
|
||||
# for stdin to close.
|
||||
close r_in; close w_in;
|
||||
close r_out; close w_out;
|
||||
close r_err; close w_err;
|
||||
|
||||
# Now run the child function, which can use stdin, stdout, and stderr
|
||||
# normally.
|
||||
child_fn
|
||||
)
|
||||
(
|
||||
# Parent process. Open the opposite side of each pipe into three new
|
||||
# file handles.
|
||||
fdopen w_in "w" \child_in
|
||||
fdopen r_out "r" \child_out
|
||||
fdopen r_err "r" \child_err
|
||||
|
||||
# Close unused file handles. We don't close the ones we fdopened
|
||||
# because they are still in play (i.e. fdopen does not dup).
|
||||
close r_in;
|
||||
close w_out;
|
||||
close w_err;
|
||||
|
||||
# Return the child's pid, stdin, stdout, and stderr.
|
||||
next pid child_in child_out child_err
|
||||
)
|
||||
)
|
||||
72
Task/Fork/Fexl/fork-3.fexl
Normal file
72
Task/Fork/Fexl/fork-3.fexl
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
\test_pipe =
|
||||
(\next
|
||||
print "== test_pipe";nl;
|
||||
|
||||
### Handy
|
||||
|
||||
# Echo entire contents of stream fh to stdout.
|
||||
\file_print ==
|
||||
(\fh\next
|
||||
fgetc fh \ch
|
||||
long_lt ch 0 next;
|
||||
putchar ch;
|
||||
file_print fh next
|
||||
)
|
||||
|
||||
# Show a stream with a descriptive label.
|
||||
\show_stream =
|
||||
(\label\fh\next
|
||||
print "[ ";print label;print ":";nl;
|
||||
file_print fh;
|
||||
print "]";nl;
|
||||
next
|
||||
)
|
||||
|
||||
### Here is a child function to try with spawn.
|
||||
|
||||
\child_fn =
|
||||
(\next
|
||||
print "Hello from child.";nl;
|
||||
get_stdin \stdin
|
||||
show_stream "input from parent" stdin;
|
||||
print "Good bye from child.";nl;
|
||||
die "Oops the child had an error!";
|
||||
next
|
||||
)
|
||||
|
||||
# Spawn the child.
|
||||
spawn child_fn \pid\child_in\child_out\child_err
|
||||
|
||||
# Now we can communicate with the child through its three file handles.
|
||||
print "Hello from parent, child pid = ";print pid;print ".";nl;
|
||||
|
||||
# Say something to the child.
|
||||
(
|
||||
# Override print routines for convenience.
|
||||
\print = (fwrite child_in)
|
||||
\nl = (print NL)
|
||||
|
||||
# Start talking.
|
||||
print "Hello child, I am your parent!";nl;
|
||||
print "OK, nice talking with you.";nl;
|
||||
);
|
||||
|
||||
print "The parent is now done talking to the child.";nl;
|
||||
|
||||
# Now show the child's stdout and stderr streams.
|
||||
show_stream "output from child" child_out;
|
||||
show_stream "error from child" child_err;
|
||||
|
||||
# Wait for child to finish.
|
||||
wait \pid\status
|
||||
# LATER shift and logical bit operators
|
||||
# LATER WEXITSTATUS and other wait macros
|
||||
\status = (long_div status 256)
|
||||
|
||||
print "Child ";print pid;print " exited with status ";
|
||||
print status;print ".";nl;
|
||||
print "Good bye from parent.";nl;
|
||||
|
||||
print "test_pipe completed successfully.";nl;
|
||||
next
|
||||
)
|
||||
1
Task/Fork/Fexl/fork-4.fexl
Normal file
1
Task/Fork/Fexl/fork-4.fexl
Normal file
|
|
@ -0,0 +1 @@
|
|||
test_pipe;
|
||||
Loading…
Add table
Add a link
Reference in a new issue