zsh-users
 help / color / mirror / code / Atom feed
* =() and &! don't go together?
@ 2011-08-25 11:22 Štěpán Němec
  2011-08-28 16:19 ` Peter Stephenson
       [not found] ` <20110828171925.0b1510ea__32210.3851977319$1314548645$gmane$org@pws-pc.ntlworld.com>
  0 siblings, 2 replies; 3+ messages in thread
From: Štěpán Němec @ 2011-08-25 11:22 UTC (permalink / raw)
  To: zsh-users

It looks like when &! is used (i.e., "program =(computation) &!"), the
temporary file created by =() does not exist at the point the command
tries to access it. Is there a solution to this?

(I mean, for people more knowledgable than me it's probably obvious from
the way &! works; what I'm wondering is if it could either be fixed
somehow, or what the simplest workaround is.)

-- 
Štěpán


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: =() and &! don't go together?
  2011-08-25 11:22 =() and &! don't go together? Štěpán Němec
@ 2011-08-28 16:19 ` Peter Stephenson
       [not found] ` <20110828171925.0b1510ea__32210.3851977319$1314548645$gmane$org@pws-pc.ntlworld.com>
  1 sibling, 0 replies; 3+ messages in thread
From: Peter Stephenson @ 2011-08-28 16:19 UTC (permalink / raw)
  To: zsh-users

On Thu, 25 Aug 2011 13:22:09 +0200
Štěpán Němec <stepnem@gmail.com> wrote:
> It looks like when &! is used (i.e., "program =(computation) &!"), the
> temporary file created by =() does not exist at the point the command
> tries to access it. Is there a solution to this?

I think the basic problem here is that =(...) uses a temporary file, and
if you've told the shell to forget about the process it's just created
there's nothing to tidy up the temporary file.  I would have guessed it
would simply not tidy up the file at all, however instead it seems it
tidies it up even before it's used, which doesn't seem particularly
useful.

You can work around both problems with

(program =(computation)) &!

In this case, the subshell will hang around to tidy up the temporary
file.

The following patch does what I think is the best we can, namely just
leave the files lying around but document the fact and the workaround.

Index: Doc/Zsh/expn.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/expn.yo,v
retrieving revision 1.139
diff -p -u -r1.139 expn.yo
--- Doc/Zsh/expn.yo	14 Aug 2011 23:19:22 -0000	1.139
+++ Doc/Zsh/expn.yo	28 Aug 2011 16:15:23 -0000
@@ -471,6 +471,18 @@ example(tt({ paste <LPAR()cut -f1) var(f
 The extra processes here are
 spawned from the parent shell which will wait for their completion.
 
+Another problem arises any time a job with a substitution that requires
+a temporary file is disowned by the shell, including the case where
+`tt(&!)' or `tt(&|)' appears at the end of a command containing a
+subsitution.  In that case the temporary file will not be cleaned up as
+the shell no longer has any memory of the job.  A workaround is to use
+a subshell, for example,
+
+example(LPAR()mycmd =(myoutput)RPAR() &!)
+
+as the forked subshell will wait for the command to finish then remove
+the temporary file.
+
 texinode(Parameter Expansion)(Command Substitution)(Process Substitution)(Expansion)
 sect(Parameter Expansion)
 cindex(parameter expansion)
Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.203
diff -p -u -r1.203 exec.c
--- Src/exec.c	17 Aug 2011 20:26:05 -0000	1.203
+++ Src/exec.c	28 Aug 2011 16:15:23 -0000
@@ -405,7 +405,7 @@ execcursh(Estate state, int do_exec)
     state->pc++;
 
     if (!list_pipe && thisjob != list_pipe_job && !hasprocs(thisjob))
-	deletejob(jobtab + thisjob);
+	deletejob(jobtab + thisjob, 0);
     cmdpush(CS_CURSH);
     execlist(state, 1, do_exec);
     cmdpop();
@@ -1434,7 +1434,7 @@ execpline(Estate state, wordcode slcode,
 	    zclose(opipe[0]);
 	}
 	if (how & Z_DISOWN) {
-	    deletejob(jobtab + thisjob);
+	    deletejob(jobtab + thisjob, 1);
 	    thisjob = -1;
 	}
 	else
@@ -1484,7 +1484,7 @@ execpline(Estate state, wordcode slcode,
 		    printjob(jn, !!isset(LONGLISTJOBS), 1);
 		}
 		else if (newjob != list_pipe_job)
-		    deletejob(jn);
+		    deletejob(jn, 0);
 		else
 		    lastwj = -1;
 	    }
@@ -1588,7 +1588,7 @@ execpline(Estate state, wordcode slcode,
 
 	    if (list_pipe && (lastval & 0200) && pj >= 0 &&
 		(!(jn->stat & STAT_INUSE) || (jn->stat & STAT_DONE))) {
-		deletejob(jn);
+		deletejob(jn, 0);
 		jn = jobtab + pj;
 		if (jn->gleader)
 		    killjb(jn, lastval & ~0200);
@@ -1596,7 +1596,7 @@ execpline(Estate state, wordcode slcode,
 	    if (list_pipe_child ||
 		((jn->stat & STAT_DONE) &&
 		 (list_pipe || (pline_level && !(jn->stat & STAT_SUBJOB)))))
-		deletejob(jn);
+		deletejob(jn, 0);
 	    thisjob = pj;
 
 	}
@@ -4271,7 +4271,7 @@ execshfunc(Shfunc shf, LinkList args)
 	 * would be filled by a recursive function. */
 	last_file_list = jobtab[thisjob].filelist;
 	jobtab[thisjob].filelist = NULL;
-	deletejob(jobtab + thisjob);
+	deletejob(jobtab + thisjob, 0);
     }
 
     if (isset(XTRACE)) {
@@ -4300,7 +4300,7 @@ execshfunc(Shfunc shf, LinkList args)
     cmdsp = ocsp;
 
     if (!list_pipe)
-	deletefilelist(last_file_list);
+	deletefilelist(last_file_list, 0);
 }
 
 /* Function to execute the special type of command that represents an *
Index: Src/jobs.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/jobs.c,v
retrieving revision 1.87
diff -p -u -r1.87 jobs.c
--- Src/jobs.c	16 Aug 2011 15:27:08 -0000	1.87
+++ Src/jobs.c	28 Aug 2011 16:15:23 -0000
@@ -269,7 +269,7 @@ handle_sub(int job, int fg)
 	       sleep, the rest will be executed by a sub-shell,
 	       but the parent shell gets notified for the
 	       sleep.
-	       deletejob(sj); */
+	       deletejob(sj, 0); */
 	    /* If this super-job contains only the sub-shell,
 	       we have to attach the tty to its process group
 	       now. */
@@ -955,7 +955,7 @@ printjob(Job jn, int lng, int synch)
 	if (jn->stat & STAT_DONE) {
 	    if (should_report_time(jn))
 		dumptime(jn);
-	    deletejob(jn);
+	    deletejob(jn, 0);
 	    if (job == curjob) {
 		curjob = prevjob;
 		prevjob = job;
@@ -1085,7 +1085,7 @@ printjob(Job jn, int lng, int synch)
     if (jn->stat & STAT_DONE) {
 	if (should_report_time(jn))
 	    dumptime(jn);
-	deletejob(jn);
+	deletejob(jn, 0);
 	if (job == curjob) {
 	    curjob = prevjob;
 	    prevjob = job;
@@ -1100,12 +1100,13 @@ printjob(Job jn, int lng, int synch)
 
 /**/
 void
-deletefilelist(LinkList file_list)
+deletefilelist(LinkList file_list, int disowning)
 {
     char *s;
     if (file_list) {
 	while ((s = (char *)getlinknode(file_list))) {
-	    unlink(s);
+	    if (!disowning)
+		unlink(s);
 	    zsfree(s);
 	}
 	zfree(file_list, sizeof(struct linklist));
@@ -1141,7 +1142,7 @@ freejob(Job jn, int deleting)
 	/* careful in case we shrink and move the job table */
 	int job = jn - jobtab;
 	if (deleting)
-	    deletejob(jobtab + jn->other);
+	    deletejob(jobtab + jn->other, 0);
 	else
 	    freejob(jobtab + jn->other, 0);
 	jn = jobtab + job;
@@ -1161,13 +1162,17 @@ freejob(Job jn, int deleting)
 /*
  * We are actually finished with this job, rather
  * than freeing it to make space.
+ *
+ * If "disowning" is set, files associated with the job are not
+ * actually deleted --- and won't be as there is nothing left
+ * to clear up.
  */
 
 /**/
 void
-deletejob(Job jn)
+deletejob(Job jn, int disowning)
 {
-    deletefilelist(jn->filelist);
+    deletefilelist(jn->filelist, disowning);
     if (jn->stat & STAT_ATTACH) {
 	attachtty(mypgrp);
 	adjustwinsize(0);
@@ -1343,7 +1348,7 @@ zwaitjob(int job, int wait_cmd)
 	    child_block();
 	}
     } else {
-	deletejob(jn);
+	deletejob(jn, 0);
 	pipestats[0] = lastval;
 	numpipestats = 1;
     }
@@ -1366,7 +1371,7 @@ waitjobs(void)
     if (jn->procs || jn->auxprocs)
 	zwaitjob(thisjob, 0);
     else {
-	deletejob(jn);
+	deletejob(jn, 0);
 	pipestats[0] = lastval;
 	numpipestats = 1;
     }
@@ -1494,7 +1499,7 @@ spawnjob(void)
 	}
     }
     if (!hasprocs(thisjob))
-	deletejob(jobtab + thisjob);
+	deletejob(jobtab + thisjob, 0);
     else
 	jobtab[thisjob].stat |= STAT_LOCKED;
     thisjob = -1;
@@ -2070,7 +2075,7 @@ bin_fg(char *name, char **argv, Options 
 		waitjobs();
 		retval = lastval2;
 	    } else if (ofunc == BIN_DISOWN)
-	        deletejob(jobtab + job);
+	        deletejob(jobtab + job, 1);
 	    break;
 	case BIN_JOBS:
 	    printjob(job + (oldjobtab ? oldjobtab : jobtab), lng, 2);
@@ -2106,7 +2111,7 @@ bin_fg(char *name, char **argv, Options 
 #endif
                          pids);
 	    }
-	    deletejob(jobtab + job);
+	    deletejob(jobtab + job, 1);
 	    break;
 	}
 	thisjob = ocj;
 


-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: =() and &! don't go together?
       [not found] ` <20110828171925.0b1510ea__32210.3851977319$1314548645$gmane$org@pws-pc.ntlworld.com>
@ 2011-09-07 18:23   ` Štěpán Němec
  0 siblings, 0 replies; 3+ messages in thread
From: Štěpán Němec @ 2011-09-07 18:23 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-users

On Sun, 28 Aug 2011 18:19:25 +0200
Peter Stephenson wrote:

> On Thu, 25 Aug 2011 13:22:09 +0200
> Štěpán Němec <stepnem@gmail.com> wrote:
>> It looks like when &! is used (i.e., "program =(computation) &!"), the
>> temporary file created by =() does not exist at the point the command
>> tries to access it. Is there a solution to this?

[...]

> You can work around both problems with
>
> (program =(computation)) &!

[...]

> The following patch does what I think is the best we can, namely just
> leave the files lying around but document the fact and the workaround.

[...]

On Mon, 29 Aug 2011 17:59:32 +0200
Bart Schaefer wrote:

> [>workers]

[...]

> Or { ... }&! too.

Thank you both very much for the suggestions and the fix! (I can't
really comment on whether the patch is the Right Thing to do or not, in
any case it does seem to fix the problem.)

-- 
Štěpán


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-09-07 18:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-25 11:22 =() and &! don't go together? Štěpán Němec
2011-08-28 16:19 ` Peter Stephenson
     [not found] ` <20110828171925.0b1510ea__32210.3851977319$1314548645$gmane$org@pws-pc.ntlworld.com>
2011-09-07 18:23   ` Štěpán Němec

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).