Follow up.
I worked around the stdin issue by using an input file.
Using Mailbox to a spawned process works, except if there is a lot of output from that process.
Code: Select all
GRT$ @tp "dir sys$common:[*...]"
cmd: dir sys$common:[*...]
spawn: 7ACA38BC, len=21 'dir sys$common:[*...]',in=_MBA2547: out=_MBA2548:[].;
spawn pid=0x000005a9
....
DTACTN.M_BM;1 DTACTN.M_M_BM;1 DTACTN.M_PM;1 DTACTN.T_BM;1
%SYSTEM-F-ACCVIO, access violation, reason mask=14, virtual address=FFFFFFFF9999
999A, PC=FFFF830007FEC818, PS=0000001B
Improperly handled condition, image exit forced.
Signal arguments: Number = 0000000000000005
Name = 000000000000000C
0000000000000014
FFFFFFFF9999999A
FFFF830007FEC818
000000000000001B
Register dump:
RAX = 0000000000000200 RDI = 000000007ACA2570 RSI = 000000007ACA24D0
RDX = FFFFFFFF8AD0F420 RCX = FFFFFFFF8AD0F420 R8 = 000000007ACA2B20
R9 = 0000000000000000 RBX = 0000000000000006 RBP = 000000007ACA20C0
R10 = 0000000000002804 R11 = FFFFFFFF9999999A R12 = 000000001AA051AF
R13 = 0000000000000018 R14 = 000000007ACA2890 R15 = 000000007ACA24D0
RIP = FFFF830007FEC818 RSP = 000000007ACA2078 SS = 000000000000001B
Error: Child process gone away, sts=1000000c
stop child pid=000005A9
Tried with MPA (real pipes just hangs...)
So tried in IA64 latest releases VSI C V7.4-001 on OpenVMS IA64 V8.4-2L3
Code: Select all
GRT$ @tp dir
cmd: DIR
spawn: 7ACB3100, len=3 'DIR',in=_MBA3286: out=_MBA3287:[].;
spawn pid=0x2e20e9ee
Improperly handled condition, bad stack or no handler specified.
poll: stdin EOF, write logout
Signal arguments: Number = 0000000000000007
Name = 000000001035DF48
000000007ACC5B00
0000000000000000
FFFFFFFF800AC330
000000000000001B
FFFFFFFF805DD030
000000000000001B
Register dump:
R0 = 0000000000000000 R1 = FFFFFFFF8842AC00 R2 = 000000007ACC5B00
R3 = 000000007FFEFFA8 R4 = FFFFFFFF896B1400 R5 = 0000000000000008
R6 = 000000007FF67F30 R7 = 0000000000000002 R8 = 0009804C0270033F
R9 = 0000000000000000 R10 = FFFFFFFF805E78A0 R11 = 0009804C0270033F
SP = 000000007ACC5AF0 TP = 0000000000000000 R14 = 0000000000000000
R15 = 000000007ACC5B08 R16 = 000000007ACC5B00 R17 = 000000007FF43F78
R18 = 0000000000000000 R19 = 0000000000000000 R20 = 0000000000000003
R21 = 0000000000000000 R22 = 0000000000000000 R23 = E000000000000050
R24 = 0000000000000004 R25 = 0000000000000005 R26 = 000000007ACC5B4B
R27 = FFFFFFFF8822E398 R28 = 000000000000000F R29 = 0000000000000042
R30 = 000000000000000F R31 = 0000000000000000 PC = FFFFFFFF805DD030
BSP/STORE = 000007FDBFFD4000 / 000007FDBFFD4000 PSR = 0000101308026010
IIPA = 0000000000000000
B0 = FFFFFFFF805DD030 B6 = FFFFFFFF805E78A0 B7 = 0000000000000002
Interrupted Frame RSE Backing Store, Size = 20 registers
R32 = 0000000000000003 R33 = 000000007AEE1D50 R34 = 0000000000000005
R35 = FFFFFFFF800AC330 R36 = 000000000000000B R37 = 000000000000000F
R38 = C000000000000000 R39 = 0000000000000003 R40 = 000000007ACC5B00
R41 = FFFFFFFF8822CAA8 R42 = FFFFFFFF800DDFE0 R43 = FFFFFFFF804DC5A0
R44 = C000000000000000 R45 = 80000000FF565563 R46 = FFFFFFFF8842AC00
R47 = 000000001035DF48 R48 = 000000007ACC5B00 R49 = 0000000000000000
R50 = FFFFFFFF800AC330 R51 = 000000000000001B
DISK_USER3:[GRT.pipes]
poll: timeout
stop child pid=2E20E9EE
MPA hangs which is expected..
But not good
So tried VSI C V7.4-001 on OpenVMS IA64 V8.4-2L1
Code: Select all
GRT$ @tp dir
cmd: DIR
spawn: 7ACB1100, len=3 'DIR',in=_MBA39500: out=_MBA39501:[].;
spawn pid=0x30cffabf
poll: socket operation on non-socket, errno=38
stop child pid=30CFFABF
Messy, looking forward to 9.2.3 and the associated fixes on IA64.
Added in 1 minute 31 seconds:
sample code, not pretty just testing code
Code: Select all
/*
* copyright 2024, TS Solutions Pty Ltd
* code to test using C pipe() (i.e. MBX's)
* to communicate with a LIB$SPAWN process
* DECC$PIPE_BUFFER_SIZE DECC$PIPE_BUFFER_QUOTA
* DECC$STREAM_PIPE
*/
#include <starlet.h>
#include <ssdef.h>
#include <stdlib.h>
#include <stdio.>
#include "stat.h"
#include "statvfs.h"
#include "string.h"
#include <unistd.h>
#include <unixio.h>
#include <lib$routines.h>
#include <socket.h>
#include <descrip.h>
#include <errno.h>
#include <poll.h>
#include <fcntl.h>
int decc$write_eof_to_mbx( int );
main(int argc, char **argv)
{
int sts=0, child_sts=0;
int stdini;
stat_t st_buf;
int p0_in[2], p0_out[2];
int syscmd_fd;
int chan, poll_timeout=100;
char p0_in_name[4096], p0_out_name[4096];
struct dsc$descriptor_s p0_in_dsc;
struct dsc$descriptor_s p0_out_dsc;
struct dsc$descriptor_s command_dsc;
char p0_in_databuff[32000];
char p0_out_databuff[32000];
char command_str[4096];
void *command_ptr=NULL, *p0_in_ptr=NULL;
int spawn_flags;
pid_t child_pid, test_pid;
struct pollfd poll_fds[2];
nfds_t poll_nfds;
int i,len, iomode, poll_eof;
p0_in_dsc.dsc$a_pointer=p0_in_name;
p0_in_dsc.dsc$b_class = DSC$K_CLASS_S;
p0_in_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
p0_out_dsc.dsc$a_pointer=p0_out_name;
p0_out_dsc.dsc$b_class = DSC$K_CLASS_S;
p0_out_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
command_dsc.dsc$a_pointer=command_str;
command_dsc.dsc$b_class = DSC$K_CLASS_S;
command_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
syscmd_fd=open("TT:",O_RDONLY);
// p0_in[0] is the child input, [1] output from parent
sts=pipe(p0_in);
if(sts == -1)
{
printf("Error creating pipes p0_in\n");
}
// p0_out[0] is the child output, [1]parent input from child
sts=pipe(p0_out,0,1024,4096);
if(sts == -1)
{
printf("Error creating pipes p0_out\n");
}
//
strncpy(command_str,"",sizeof(command_str));
command_ptr=NULL;
if(argc>1 && strnlen(argv[1],10)>1)
{
// printf("argc=%d '%s'\n",argc,argv[1]);
command_ptr=&command_dsc;
// if does not start with pipe insert "pipe"
// ensure end of command is " ; logout/brief "
// if(strncasecmp("pipe ",argv[1],4) != 0)
// {
// snprintf(command_str,sizeof(command_str)
// ,"pipe %s ; logout/brief ",argv[1]);
// }
// else
{
strncpy(command_str,argv[1],sizeof(command_str));
}
if(command_str != NULL)printf("cmd: %s\n",command_str);
}
//
command_dsc.dsc$w_length=strlen(command_str);
// set up spawn input device
getname(p0_in[1],p0_in_name);
p0_in_dsc.dsc$w_length=strlen(p0_in_name);
//
// set up spawn output device
getname(p0_out[0],p0_out_name);
p0_out_dsc.dsc$w_length=strlen(p0_out_name);
// now to spawn
printf("spawn: %p, len=%d '%.100s',in=%s out=%s\n"
,command_ptr,command_dsc.dsc$w_length,command_dsc.dsc$a_pointer
,p0_in_dsc.dsc$a_pointer,p0_out_dsc.dsc$a_pointer);
//
child_sts=0;
spawn_flags=1;
sts=lib$spawn( command_ptr
,&p0_in_dsc
,&p0_out_dsc
,&spawn_flags
,0 /* proc_name */
,&child_pid /* proc_id */
,&child_sts /* comp_status */
,0 /* efn */
,0 /* ast() */
,0 /* ast arg */
,0 /* prompt_str */
,0 /* cli_str */
,0); /* table */
if(sts != 1)
{
lib$signal(sts);
}
if(child_pid==0)
{
printf("spawn: pid=0 err %d\n",sts);
exit;
}
printf("spawn pid=0x%08x\n",child_pid);
// now use poll to transfer data
poll_fds[1].fd=syscmd_fd; // sys$command 0; // ie stdin
poll_fds[1].events=POLLIN;
//
poll_fds[0].fd=p0_out[0]; // ie from child
poll_fds[0].events=POLLIN;
// printf("fd0=%d %x fd1=%d %x\n"
// ,poll_fds[0].fd,poll_fds[0].events
// ,poll_fds[1].fd,poll_fds[1].events);
if( kill(child_pid,0) == -1)
{
printf("\n\nChild process gone away, sts=%08x\n", child_sts);
exit(0);
}
//
poll_nfds=2;
// poll_nfds=1;
sts=0;
poll_eof=0;
while(poll_eof==0)
{
if( kill(child_pid,0) == -1)
{
printf("\n\nError: Child process gone away, sts=%08x\n", child_sts);
poll_eof=-1;
break; // exit(1); /* can't recover */
}
// poll with timeout
sts=poll(poll_fds, poll_nfds, poll_timeout);
if(sts==-1)
{
printf("poll: %.100s, errno=%d\n", strerror(errno), errno);
// if (errno == EINVAL)
break; // exit(1); /* can't recover */
}
if(sts==0)
{
printf("poll: timeout\n");
if(command_ptr != NULL) break;
// poll_eof=1;
if( kill(child_pid,0) == -1)
{
printf("\n\nChild process gone away, sts=%08x\n", child_sts);
poll_eof=-1;
break; // exit(1); /* can't recover */
}
}
for(i=0;i<poll_nfds; i++)
{
if((poll_fds[i].revents & POLLERR ) != 0)
{
printf("poll: error on fd=%d\n",poll_fds[i].fd);
poll_eof=1;
sts=-1;
break;
}
/* child */
if(poll_fds[i].fd==p0_out[0])
{
// printf("x fd=%d; events: %s%s%s\n", poll_fds[i].fd,
// (poll_fds[i].revents & POLLIN) ? "POLLIN " : "",
// (poll_fds[i].revents & POLLHUP) ? "POLLHUP " : "",
// (poll_fds[i].revents & POLLERR) ? "POLLERR " : "");
sts=0;
if((poll_fds[i].revents & POLLIN ) != 0)
{
// printf("get child data\n");
len=read(poll_fds[i].fd
,p0_out_databuff
,sizeof(p0_out_databuff)-2);
if(len==-1) perror("child read: ");
p0_out_databuff[len]='\n';
len++;
p0_out_databuff[len]='\0';
// printf("--%100s\n", p0_out_databuff);
sts=write(STDOUT_FILENO,p0_out_databuff,len);
if(sts==-1) perror("pout: ");
// printf("poll: child->%d '%.60s'\n",len,p0_out_databuff);
}
if((poll_fds[i].revents & POLLHUP ) != 0)
{
printf("pout: EOF\n");
poll_eof=1;
poll_fds[i].fd=-1;
sts=-1;
break;
}
}
/* parent */
if(poll_fds[i].fd==syscmd_fd)
{
// printf("ww fd=%d; events: %s%s%s\n", poll_fds[i].fd,
// (poll_fds[i].revents & POLLIN) ? "POLLIN " : "",
// (poll_fds[i].revents & POLLHUP) ? "POLLHUP " : "",
// (poll_fds[i].revents & POLLERR) ? "POLLERR " : "");
sts=0;
if((poll_fds[i].revents & POLLIN ) != 0)
{
// printf("get parent data\n");
len=read(poll_fds[i].fd
,p0_in_databuff
,sizeof(p0_in_databuff));
// printf("parent len=%d %50s\n",len,p0_in_databuff);
if(len==-1)
{
perror("error readin parent data");
break;
}
if(len==0)
{
poll_fds[i].fd=-1; // mark as EOF
printf("poll: stdin EOF, write logout\n");
//
// if(argc>0) //strnlen(argv[1],255) == 0 )
{
strncpy(p0_in_databuff,"logout",sizeof(p0_in_databuff));
sts=write(p0_in[1],p0_in_databuff,strlen(p0_in_databuff));
if(sts==-1) perror("pout: ");
// write EOF & or ^Z
sts=write(p0_in[1],"\032",1);
if(sts==-1) perror("pout: ");
// sts=decc$write_eof_to_mbx(p0_in[1]);
// if(sts==-1) perror("pout: ");
poll_fds[i].fd=-1; // stop polling pout
sts=0; // wait for child
poll_timeout=10;
break;
}
}
else
{
sts=write(p0_in[1],p0_in_databuff,len-1);
}
}
if((poll_fds[i].revents & POLLHUP ) != 0)
{
printf("poll: pin POLLHUP\n");
poll_fds[i].fd=-1; // stop polling pout
sts=0; // wait for child
break;
}
}
}
}
close(p0_in[1]);
close(p0_out[0]);
if(child_pid !=0)
{
printf("stop child pid=%08X\n",child_pid);
sts=sys$delprc((unsigned int *)&child_pid,NULL,0);
// if(sts !=SS$_NORMAL) lib$signal(sts);
}
}