[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Possible fix for the signal-handling problem in es-0.9-beta1.tar.gz



+ Loren James Rittle <rittle@latour.rsch.comm.mot.com>:

| I can confirm that this tarball:
| 
| ftp://ftp.sys.toronto.edu/pub/es/es-0.9-beta1.tar.gz
| 
| matches the one I have locally.

Um yes, I think that means that the diff Soren sent me in September
1997 was never made official.

I'll attach it here, for everyone to look at.  Possibly it should make
it into the official distribution?  (Or possibly not, without further
refinement - see below.)


Let me shortly reiterate its purpose:  This patch was meant to address
a problem with %readfrom and %writeto:  The two functions implementing
the <{...} and >{...} functionality.

The problem does not exist at all on systems which have /dev/fd/, for
there this is handled by builtins $&readfrom and $&writeto.  But for

But on other systems, these functions create a temporary file (or
fifo, if you preferred) /tmp/es.$var.$pid for one process to write to
and the other to read from.  Here, $var holds the number of the file
descriptor used in the parent shell.  However, since $pid is only set
when the shell starts up, and never changes when it forks, you could
get name collisions that way.

The example I quoted when first reporting this was as follows:

; for (x=1 2 3) { cat <{echo $x} & }
15946
15947
15948
; mknod: /tmp/es._devfd0.15685: File exists
mknod: /tmp/es._devfd0.15685: File exists
2
1
3

;

Those want more details could go back and read the thread "Flaw in
%readfrom and %writeto" from September 1997, if they have kept an
archive of the list.


Anyway, I have found that there is a problem with Soren's solution.
He introduced a new primitive getpid which returns the pid of the
current process, and replaces $pid in the definition of %readfrom and
%writeto by <=$&getpid.

So far, so good.

But he also removed the initialization of $pid from main.c and
inserted it into %batch-loop and %interactive-loop instead.  That
might not be such a clever idea, since the value of $pid can now
change in unexpected places:

; . <{echo echo hi there $pid '$pid'}
hi there 93689 93689

; fork {var pid; . <{echo echo hi there $pid '$pid'}; var pid}
pid = 93689
hi there 93689 49463
pid = 49463

(Ouch!)

So I suggest keeping the new primitive getpid and its usage in
%readfrom and %writeto (in initial.es), but to reject its application
in %batch-loop and %interactive-loop and to keep the initialization of
$pid in main.c the way it was.

Again, this is really only necessary on systems without /dev/fd/, and
I suppose it could be argued that the new primitive should only be
implemented on such systems.  But I think that complicates things too
much.
Index: CHANGES
===================================================================
RCS file: /homes/csdayton/.CVSROOT/es/CHANGES,v
retrieving revision 1.4
diff -c -r1.4 CHANGES
*** CHANGES	1997/08/12 23:59:08	1.4
--- CHANGES	1997/09/17 05:15:24
***************
*** 1,6 ****
--- 1,15 ----
  CHANGES		-*- mode: indented-text -*- ($Revision: 1.4 $)
  =======
  
+ 0.9beta to 0.9beta1
+ -------------------
+ 
+ Created a new primitive `getpid' which runs the equivalent C function
+ and replaced the special treatment of `pid' in main.c.  This means that
+ %batch-loop and %interactive-loop now update pid.  This was done because
+ %readfrom and %writeto fail when several are used in parallel and in the
+ background on OS's that do not have /dev/fd/ file systems.
+ 
  0.9-alpha2 to 0.9beta
  ---------------------
  
Index: initial.es
===================================================================
RCS file: /homes/csdayton/.CVSROOT/es/initial.es,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** initial.es	1997/04/11 20:54:33	1.1.1.1
--- initial.es	1997/09/17 05:11:38	1.2
***************
*** 1,4 ****
! # initial.es -- set up initial interpreter state ($Revision: 1.1.1.1 $)
  
  
  #
--- 1,4 ----
! # initial.es -- set up initial interpreter state ($Revision: 1.2 $)
  
  
  #
***************
*** 494,500 ****
  	fn-%readfrom = $&readfrom
  } {
  	fn %readfrom var input cmd {
! 		local ($var = /tmp/es.$var.$pid) {
  			unwind-protect {
  				$input > $$var
  				# text of $cmd is   command file
--- 494,500 ----
  	fn-%readfrom = $&readfrom
  } {
  	fn %readfrom var input cmd {
! 		local ($var = /tmp/es.$var.<=$&getpid) {
  			unwind-protect {
  				$input > $$var
  				# text of $cmd is   command file
***************
*** 510,516 ****
  	fn-%writeto = $&writeto
  } {
  	fn %writeto var output cmd {
! 		local ($var = /tmp/es.$var.$pid) {
  			unwind-protect {
  				> $$var
  				$cmd
--- 510,516 ----
  	fn-%writeto = $&writeto
  } {
  	fn %writeto var output cmd {
! 		local ($var = /tmp/es.$var.$&getpid) {
  			unwind-protect {
  				> $$var
  				$cmd
***************
*** 625,634 ****
  #	result gets set to zero when it should not be.
  
  fn-%parse	= $&parse
! fn-%batch-loop	= $&batchloop
  fn-%is-interactive = $&isinteractive
  
  fn %interactive-loop {
  	let (result = <=true) {
  		catch @ e type msg {
  			if {~ $e eof} {
--- 625,640 ----
  #	result gets set to zero when it should not be.
  
  fn-%parse	= $&parse
! 
! fn %batch-loop	{
! 	pid = <=$&getpid
! 	$&batchloop
! }
! 
  fn-%is-interactive = $&isinteractive
  
  fn %interactive-loop {
+ 	pid = <=$&getpid
  	let (result = <=true) {
  		catch @ e type msg {
  			if {~ $e eof} {
Index: main.c
===================================================================
RCS file: /homes/csdayton/.CVSROOT/es/main.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -c -r1.3 -r1.4
*** main.c	1997/08/12 23:59:28	1.3
--- main.c	1997/09/17 05:11:40	1.4
***************
*** 1,4 ****
! /* main.c -- initialization for es ($Revision: 1.3 $) */
  
  #include "es.h"
  
--- 1,4 ----
! /* main.c -- initialization for es ($Revision: 1.4 $) */
  
  #include "es.h"
  
***************
*** 44,54 ****
  	RefEnd(list);
  }
  
- /* initpid -- set $pid for this shell */
- static void initpid(void) {
- 	vardef("pid", NULL, mklist(mkstr(str("%d", getpid())), NULL));
- }
- 
  /* runesrc -- run the user's profile, if it exists */
  static void runesrc(void) {
  	char *esrc = str("%L/.esrc", varlookup("home", NULL), "\001");
--- 44,49 ----
***************
*** 184,190 ****
  		runinitial();
  	
  		initpath();
- 		initpid();
  		initsignals(runflags & run_interactive, allowquit);
  		hidevariables();
  		initenv(environ, protected);
--- 179,184 ----
Index: prim-sys.c
===================================================================
RCS file: /homes/csdayton/.CVSROOT/es/prim-sys.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -c -r1.2 -r1.3
*** prim-sys.c	1997/08/12 23:59:33	1.2
--- prim-sys.c	1997/09/17 05:11:41	1.3
***************
*** 1,4 ****
! /* prim-sys.c -- system call primitives ($Revision: 1.2 $) */
  
  #define	REQUIRE_IOCTL	1
  
--- 1,4 ----
! /* prim-sys.c -- system call primitives ($Revision: 1.3 $) */
  
  #define	REQUIRE_IOCTL	1
  
***************
*** 64,69 ****
--- 64,73 ----
  	return mklist(mkstr(mkstatus(status)), NULL);
  }
  
+ PRIM(getpid) {
+ 	return mklist(mkstr(str("%d", getpid())), NULL);
+ }
+ 
  PRIM(run) {
  	char *file;
  	if (list == NULL)
***************
*** 444,449 ****
--- 448,454 ----
  	X(umask);
  	X(cd);
  	X(fork);
+ 	X(getpid);
  	X(run);
  	X(setsignals);
  #if BSD_LIMITS