poll unable to access stdin on VMS


Topic author
greg@tssolutions.com.au
Active Contributor
Posts: 32
Joined: Wed May 29, 2024 10:29 am
Reputation: 0
Location: Australia
Status: Offline
Contact:

poll unable to access stdin on VMS

Post by greg@tssolutions.com.au » Sun Aug 04, 2024 11:40 pm

The following works fine on Linux but not VMS
VSI C x86-64 V7.5-009 (GEM 50XBR) on OpenVMS x86_64 V9.2-2

Code: Select all

#include <unistd.h>
#include <stdio.h>
#include <poll.h>
#include <string.h>
#include <errno.h>

int main(int argc, char **argv)
{
  int i,inlen, sts;
  struct pollfd poll_fds[4];
  nfds_t poll_nfds;
  char buff[4096]={0};

  poll_fds[0].fd=fileno(stdin);
  poll_fds[0].events=POLLIN;
  poll_nfds=1;

  sts=poll(poll_fds,poll_nfds,10000);
  if(sts<0)
  {
     printf("ppoll: %.100s, errno=%d\n", strerror(errno), errno);
  }
  for(i=0; i<poll_nfds;i++)
  {
     if((poll_fds[i].revents & POLLIN) !=0 )
     {
       inlen=read(poll_fds[i].fd,buff,sizeof(buff));
       printf("read[%d]: %.60s\n",inlen, buff);
     }
  }
  printf("sts=%d revents=%08x\n",sts, poll_fds[0].revents);

}
linux>
$ ./t.exe
en
read[3]: en

sts=1 revents=00000001

vms>
$ run test_poll
ppoll: i/o error, errno=5
sts=-1 revents=00000000
Last edited by greg@tssolutions.com.au on Mon Aug 05, 2024 12:25 am, edited 1 time in total.
gt (260295)
VMS Ambassador
Downunder


pustovetov
VSI Expert
Valued Contributor
Posts: 52
Joined: Thu Sep 14, 2023 1:26 am
Reputation: 0
Status: Offline

Re: poll unable to access stdin on VMS

Post by pustovetov » Mon Aug 05, 2024 1:31 am

greg@tssolutions.com.au wrote:
Sun Aug 04, 2024 11:40 pm
The following works fine on Linux but not VMS
VSI C x86-64 V7.5-009 (GEM 50XBR) on OpenVMS x86_64 V9.2-2
Oops... I've fixed it. Thank you for the bug report.

Code: Select all

$ r poll
ppoll: i/o error, errno=5
sts=-1 revents=00000000
$define DECC$SHR WORK:[xxxxx.ACRTL.BIN]DECC$SHR.EXE
$ r poll
en
read[3]: en

sts=1 revents=00000001


Topic author
greg@tssolutions.com.au
Active Contributor
Posts: 32
Joined: Wed May 29, 2024 10:29 am
Reputation: 0
Location: Australia
Status: Offline
Contact:

Re: poll unable to access stdin on VMS

Post by greg@tssolutions.com.au » Mon Sep 23, 2024 11:32 pm

Still a problem with
VSI C x86-64 X7.6-028 (GEM 50Y92) on OpenVMS x86_64 V9.2-2
gt (260295)
VMS Ambassador
Downunder


pustovetov
VSI Expert
Valued Contributor
Posts: 52
Joined: Thu Sep 14, 2023 1:26 am
Reputation: 0
Status: Offline

Re: poll unable to access stdin on VMS

Post by pustovetov » Tue Sep 24, 2024 1:34 am

greg@tssolutions.com.au wrote:
Mon Sep 23, 2024 11:32 pm
Still a problem with
VSI C x86-64 X7.6-028 (GEM 50Y92) on OpenVMS x86_64 V9.2-2
The problem was in CRTL (DECC$SHR), not VSI C. So you need to wait for a CRTL update (V9.2-3).


Topic author
greg@tssolutions.com.au
Active Contributor
Posts: 32
Joined: Wed May 29, 2024 10:29 am
Reputation: 0
Location: Australia
Status: Offline
Contact:

Re: poll unable to access stdin on VMS

Post by greg@tssolutions.com.au » Tue Oct 01, 2024 8:27 am

A related issue, when I create a fd based on a MPA device, poll() does not work.
Same code with MBA works.
gt (260295)
VMS Ambassador
Downunder


pustovetov
VSI Expert
Valued Contributor
Posts: 52
Joined: Thu Sep 14, 2023 1:26 am
Reputation: 0
Status: Offline

Re: poll unable to access stdin on VMS

Post by pustovetov » Wed Oct 02, 2024 3:45 am

greg@tssolutions.com.au wrote:
Tue Oct 01, 2024 8:27 am
A related issue, when I create a fd based on a MPA device, poll() does not work.
Same code with MBA works.
Can you give me an example? I tried to get the error with a MPA device and was unsuccessful, but I guess I did something wrong.


Topic author
greg@tssolutions.com.au
Active Contributor
Posts: 32
Joined: Wed May 29, 2024 10:29 am
Reputation: 0
Location: Australia
Status: Offline
Contact:

Re: poll unable to access stdin on VMS

Post by greg@tssolutions.com.au » Wed Oct 02, 2024 9:34 am

Maybe fixed in CRTL update (V9.2-3)?
gt (260295)
VMS Ambassador
Downunder


Topic author
greg@tssolutions.com.au
Active Contributor
Posts: 32
Joined: Wed May 29, 2024 10:29 am
Reputation: 0
Location: Australia
Status: Offline
Contact:

Re: poll unable to access stdin on VMS

Post by greg@tssolutions.com.au » Tue Oct 15, 2024 10:36 pm

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);
  }
}
gt (260295)
VMS Ambassador
Downunder


Topic author
greg@tssolutions.com.au
Active Contributor
Posts: 32
Joined: Wed May 29, 2024 10:29 am
Reputation: 0
Location: Australia
Status: Offline
Contact:

Re: poll unable to access stdin on VMS

Post by greg@tssolutions.com.au » Thu Nov 21, 2024 10:56 pm

Now have 9.2-3
poll() returns a POLLNVAL for a VMS pipe device, including stdin...
Works fine for MBX devices and files.
Last edited by greg@tssolutions.com.au on Thu Nov 21, 2024 11:17 pm, edited 1 time in total.
gt (260295)
VMS Ambassador
Downunder


pustovetov
VSI Expert
Valued Contributor
Posts: 52
Joined: Thu Sep 14, 2023 1:26 am
Reputation: 0
Status: Offline

Re: poll unable to access stdin on VMS

Post by pustovetov » Fri Nov 22, 2024 2:57 am

greg@tssolutions.com.au wrote:
Thu Nov 21, 2024 10:56 pm
Now have 9.2-3
poll() returns a POLLNVAL for a VMS pipe device, including stdin...
Works fine for MBX devices and files.
I've tried and got it

Code: Select all

$ tp DIR
cmd: dir
spawn: 7ACC18BC, len=3 'dir',in=_MBA29382: out=_MBA29383:[].;
spawn pid=0x00002d04

Directory DISK$WORK:[PUSTOVETOV.test]

catopen.DIR;1       common.mk;1         CUnit.DIR;1         curses.DIR;1
exec.DIR;1          fcntl.DIR;1         f_info.DIR;1        iconv.DIR;1
ifaddrs.DIR;1       inet.DIR;1          inttypes.DIR;1      jumps.DIR;1
locale.DIR;1        Makefile.vms;1      math.DIR;1          mman.DIR;1
multithread.DIR;1   netdb.DIR;1         pipe.DIR;1          poll.DIR;1
pwd.DIR;1           sem.DIR;1           setenv.DIR;1        shm.DIR;1
signal.DIR;1        socket.DIR;1        ssio.DIR;1          stdio.DIR;1
stdlib.DIR;1        string.DIR;1        strtod.DIR;1        test_pipe.c;1
test_pipe.EXE;1     test_pipe.OBJ;1     time.DIR;1          uio.DIR;1
unistd.DIR;1        unixlib.DIR;1       wait.DIR;1          wchar.DIR;1
XML.DIR;1

Total of 41 files.
poll: timeout
stop child pid=00002D04

Post Reply