Return-path: Received: from SOTONB.PHYS.SOTON.AC.UK by hmivax.humgen.upenn.edu (PMDF V4.3-7 #8024) id <01HIOK0SI80W0002NX@hmivax.humgen.upenn.edu>; Tue, 25 Oct 1994 05:17:08 EDT Received: by sotona.phys.soton.ac.uk (MX V3.3 VAX) id 30936; Tue, 25 Oct 1994 09:12:22 GMT Date: Tue, 25 Oct 1994 09:12:15 +0000 (GMT) From: David Denholm Subject: Re: does popen() work ? To: bailey@hmivax.humgen.upenn.edu Cc: VMSPERL@hmivax.humgen.upenn.edu Message-id: <00986770.F7C683C0.30936@sotona.phys.soton.ac.uk> Content-transfer-encoding: 7BIT > >> is this a valid perl program ? >> >>open(p,'|create test.out') || die; >>print p "HELLO\n"; >>close(p); > >This is valid perl; I think you're being bitten by the mailbox driver here. I >suspect the subprocess has posted a read to the mailbox, and is hung in LEF, >while the parent is hung in HIB waiting for the child to complete. There must >be a way around this, but I can't think of one offhand. Anyone got any ideas? > - sorry, I forgot to mention I was still at perl5gamma, in case it matters. while I'm here, before I forget... that perlshr options file, rather than using f$environment(default) to get the current directory, could we not use the sys$disk:[] trick ? - then dont need make/mms to do any DCL lexical expansion - back to the pipe problem... - seems to work (well, not hang) if I perl -d it ! Using vms debugger on perl, it actually seems to be hanging in the lib$spawn() in popen() UH OH - if we compare the open-for-write and open-for-read cases closely, I notice THERE IS NO &flags ARG !!!!!!!!! The flags is the /nowait bit !!!!!!!!!!!!!!!!!!!!!!!! - some conclusions below are wrong, since they were written before I noticed that, but some questions arose... I append some diffs I have made to vms.c Just looking around... in pclose, we have if (!info->completion) { /* Tap them gently on the shoulder . . .*/ _cksts(sys$forcex(&info->pid,0,&abort)); sleep(1); } if (!info->completion) /* We tried to be nice . . . */ _cksts(sys$delprc(&info->pid)); fclose(info->fp); ie we kill the subprocess _then_ close the pipe. could it be that the subprocess was waiting for the EOF marker that comes with fclose() ... ie if we are writing to pipe, we should close pipe _then_ kill process. if we are reading from pipe, we kill then close - need to record mode in the status struct. Should also do the check for mode carefully... are "r+" etc valid modes for a popen ? Did anyone check that completion going to non-zero is a valid test that process has completed ? - what if subprocess is a c program that does a return(0) - would it be better to have the ast routine set a flag explicitly ? - is ast passed an arbitrary parameter - may as well pass the address of the info block..? if (strcmp(mode,"r")==0) { _cksts(lib$spawn(&cmddsc, &nl_desc, &namdsc, &flags, 0 /* name */, &info->pid, &info->completion, 0, popen_completion_ast,0,0,0,0)); } else { _cksts(lib$spawn(&cmddsc, &namdsc, 0 /* sys$output */, 0 /* name */, &info->pid, &info->completion)); } - how come popen_completion_ast is used when reading mailbox, but not writing - this is perhaps why I am stuck in HIB state ? could there be a race situation in waitpid ? while (!info->completion) { waitpid_asleep = 1; sys$hiber(); } is it possible to set waitpid_asleep to 1 , then the ast is delivered, then sys$hiber is called ? dd -- David Denholm 'official' : D.R.Denholm@southampton.ac.uk Physics dept. preferred : denholm@conmat.phys.soton.ac.uk Southampton University Tel : (0703) 592104 [work] (0489) 576733 [home] uk SO17 1BJ Fax : (0703) 585813 *** vms.c;1 --- vms.c ************** *** 254,259 struct pipe_details *next; FILE *fp; int pid; unsigned long int completion; }; --- 254,260 ----- struct pipe_details *next; FILE *fp; int pid; + int mode; /* 'r' for reading */ unsigned long int completion; }; ************** *** 303,309 cmddsc.dsc$w_length=strlen(cmd); cmddsc.dsc$a_pointer=cmd; ! if (strcmp(mode,"r")==0) { _cksts(lib$spawn(&cmddsc, &nl_desc, &namdsc, &flags, 0 /* name */, &info->pid, &info->completion, 0, popen_completion_ast,0,0,0,0)); --- 304,312 ----- cmddsc.dsc$w_length=strlen(cmd); cmddsc.dsc$a_pointer=cmd; ! info->mode=*mode; ! ! ! if (*mode=='r') { _cksts(lib$spawn(&cmddsc, &nl_desc, &namdsc, &flags, 0 /* name */, &info->pid, &info->completion, 0, popen_completion_ast,info,0,0,0)); ************** *** 306,312 if (strcmp(mode,"r")==0) { _cksts(lib$spawn(&cmddsc, &nl_desc, &namdsc, &flags, 0 /* name */, &info->pid, &info->completion, ! 0, popen_completion_ast,0,0,0,0)); } else { _cksts(lib$spawn(&cmddsc, &namdsc, 0 /* sys$output */, --- 309,315 ----- if (*mode=='r') { _cksts(lib$spawn(&cmddsc, &nl_desc, &namdsc, &flags, 0 /* name */, &info->pid, &info->completion, ! 0, popen_completion_ast,info,0,0,0)); } else { _cksts(lib$spawn(&cmddsc, &namdsc, 0 /* sys$output */, &flags, ************** *** 309,316 0, popen_completion_ast,0,0,0,0)); } else { ! _cksts(lib$spawn(&cmddsc, &namdsc, 0 /* sys$output */, ! 0 /* name */, &info->pid, &info->completion)); } info->next=open_pipes; /* prepend to list */ --- 312,320 ----- 0, popen_completion_ast,info,0,0,0)); } else { ! _cksts(lib$spawn(&cmddsc, &namdsc, 0 /* sys$output */, &flags, ! 0 /* name */, &info->pid, &info->completion, ! 0, popen_completion_ast,info,0,0,0)); } info->next=open_pipes; /* prepend to list */ ************** *** 333,338 /* get here => no such pipe open */ croak("my_pclose() - no such pipe open ???"); if (!info->completion) { /* Tap them gently on the shoulder . . .*/ _cksts(sys$forcex(&info->pid,0,&abort)); sleep(1); --- 337,353 ----- /* get here => no such pipe open */ croak("my_pclose() - no such pipe open ???"); + if (info->mode != 'r') + { + /* signal EOF and give them a chance to notice */ + fclose(info->fp); + /* assuming sleep() does sys$hibernate, perhaps we should + * tell the ast we are asleep, then sleep for longer + * - ast will wake us as soon as child completes + */ + sleep(1); + } + + if (!info->completion) { /* Tap them gently on the shoulder . . .*/ _cksts(sys$forcex(&info->pid,0,&abort)); sleep(1); ************** *** 340,346 if (!info->completion) /* We tried to be nice . . . */ _cksts(sys$delprc(&info->pid)); ! fclose(info->fp); /* remove from list of open pipes */ if (last) last->next = info->next; else open_pipes = info->next; --- 355,366 ----- if (!info->completion) /* We tried to be nice . . . */ _cksts(sys$delprc(&info->pid)); ! if (info->mode == 'r') ! { ! /* should perhaps read to EOF ? */ ! fclose(info->fp); ! } ! ! /* remove from list of open pipes */ if (last) last->next = info->next; else open_pipes = info->next;