Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

Wernher von Braun settled for a V-2 when he coulda had a V-8.


computers / comp.os.vms / Unable to replace LIB$SPAWN with vfork/execv

SubjectAuthor
* Unable to replace LIB$SPAWN with vfork/execvJake Hamby (Solid State Jake)
`* Re: Unable to replace LIB$SPAWN with vfork/execvJake Hamby (Solid State Jake)
 `- Re: Unable to replace LIB$SPAWN with vfork/execvJake Hamby (Solid State Jake)

1
Unable to replace LIB$SPAWN with vfork/execv

<58ca2e43-cbce-4f16-a508-02740817e711n@googlegroups.com>

  copy mid

https://www.novabbs.com/computers/article-flat.php?id=30866&group=comp.os.vms#30866

  copy link   Newsgroups: comp.os.vms
X-Received: by 2002:a05:620a:29c6:b0:775:78bb:5e8e with SMTP id s6-20020a05620a29c600b0077578bb5e8emr107533qkp.5.1698523167997;
Sat, 28 Oct 2023 12:59:27 -0700 (PDT)
X-Received: by 2002:a05:6870:5489:b0:1ef:516c:4aba with SMTP id
f9-20020a056870548900b001ef516c4abamr2894906oan.2.1698523167696; Sat, 28 Oct
2023 12:59:27 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!feeder1.feed.usenet.farm!feed.usenet.farm!peer01.ams4!peer.am4.highwinds-media.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.os.vms
Date: Sat, 28 Oct 2023 12:59:27 -0700 (PDT)
Injection-Info: google-groups.googlegroups.com; posting-host=2600:1700:46b0:abc0:4dfb:a82:4396:ac95;
posting-account=OGFVHQoAAAASiNAamRQec8BtkuXxYFnQ
NNTP-Posting-Host: 2600:1700:46b0:abc0:4dfb:a82:4396:ac95
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <58ca2e43-cbce-4f16-a508-02740817e711n@googlegroups.com>
Subject: Unable to replace LIB$SPAWN with vfork/execv
From: jake.ha...@gmail.com (Jake Hamby (Solid State Jake))
Injection-Date: Sat, 28 Oct 2023 19:59:27 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 3777
 by: Jake Hamby (Solid St - Sat, 28 Oct 2023 19:59 UTC

For C/C++ programs, I'd like to be able to use C RTL APIs like vfork()/execv() to replace VMS APIs like lib$spawn() in order to get the benefit of the POSIX semantics that it provides behind the scenes, like being able to pass open file descriptors and pipes to children via the vaxc$execmbx.

In reality, I've found a simple case that I can't make to work the C RTL way. The Perl port has an argv preprocessor that looks for "<", ">", "|", and "&", and emulates UNIX-style behavior by setting up file descriptors and pipes before continuing to the main Perl code.

For "&", there's a call to background_process(), which combines the argv values into a single string and runs lib$spawn() to run itself, minus the "&", then prints the spawned PID and returns SS$_NORMAL, which the parent then returns.

This works perfectly, even when the child outlives the parent:

$ perl -e "sleep 3; print 'Hello, world!'"&
00026EE1
$ Hello, world!
Subprocess JHAMBY_39391 has completed

I thought it'd be relatively simple to replace this call with vfork()/execv(), since it's self-contained, doesn't use any of the vmspipe stuff, and it's easy to test. If that worked, then I was planning to look further at popen() and when/if to use vfork/execv there. What I discovered is that vfork()/execv() can't replicate the desired behavior.

By default, the child process is killed when the parent exits, so I don't get any output. If I enable DECC$DETACHED_CHILD_PROCESS, then I get this error:

%%%%%%%%%%% OPCOM 28-OCT-2023 12:41:26.91 %%%%%%%%%%%
Message from user AUDIT$SERVER on VMSVM1
Security alarm (SECURITY) and security audit (SECURITY) on VMSVM1, system id: 65530
Auditable event: Detached process login failure
Event time: 28-OCT-2023 12:41:26.91
PID: 000274E0
Process name: JHAMBY_58118
Username: JHAMBY
Process owner: [JHAMBY]
Image name: VMSVM1$DKA0:[SYS0.SYSCOMMON.][SYSEXE]LOGINOUT.EXE
Posix UID: -2
Posix GID: -2 (%XFFFFFFFE)
Status: %RMS-E-DNR, device not ready, not mounted, or unavailable

So I don't see any way for me to replicate the behavior of putting my own process into the background, as lib$spawn() does, using vfork/exec. Is there any way to do this, or is calling lib$spawn() directly the only way to get the behavior of a subprocess that can outlive the parent and also still write to the terminal?

Regards,
Jake Hamby

Re: Unable to replace LIB$SPAWN with vfork/execv

<dafd88bc-36da-4293-bcf2-40d5e60052e6n@googlegroups.com>

  copy mid

https://www.novabbs.com/computers/article-flat.php?id=30871&group=comp.os.vms#30871

  copy link   Newsgroups: comp.os.vms
X-Received: by 2002:ac8:5307:0:b0:419:a33e:e6fa with SMTP id t7-20020ac85307000000b00419a33ee6famr238231qtn.5.1698614846572;
Sun, 29 Oct 2023 14:27:26 -0700 (PDT)
X-Received: by 2002:a05:6808:3a92:b0:3af:6406:ade7 with SMTP id
fb18-20020a0568083a9200b003af6406ade7mr2567414oib.0.1698614846359; Sun, 29
Oct 2023 14:27:26 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!border-2.nntp.ord.giganews.com!nntp.giganews.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.os.vms
Date: Sun, 29 Oct 2023 14:27:25 -0700 (PDT)
In-Reply-To: <58ca2e43-cbce-4f16-a508-02740817e711n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=2600:1700:46b0:abc0:25b9:97a4:b90f:6cf0;
posting-account=OGFVHQoAAAASiNAamRQec8BtkuXxYFnQ
NNTP-Posting-Host: 2600:1700:46b0:abc0:25b9:97a4:b90f:6cf0
References: <58ca2e43-cbce-4f16-a508-02740817e711n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <dafd88bc-36da-4293-bcf2-40d5e60052e6n@googlegroups.com>
Subject: Re: Unable to replace LIB$SPAWN with vfork/execv
From: jake.ha...@gmail.com (Jake Hamby (Solid State Jake))
Injection-Date: Sun, 29 Oct 2023 21:27:26 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Lines: 131
 by: Jake Hamby (Solid St - Sun, 29 Oct 2023 21:27 UTC

On Saturday, October 28, 2023 at 12:59:29 PM UTC-7, Jake Hamby wrote:
>
> So I don't see any way for me to replicate the behavior of putting my own process into the background, as lib$spawn() does, using vfork/exec. Is there any way to do this, or is calling lib$spawn() directly the only way to get the behavior of a subprocess that can outlive the parent and also still write to the terminal?

After spending quite a bit more time on the problem, I finally have an initial version of a "fast path" for VMS Perl that can use vfork()/execv() under conditions that I know are safe:

- The command starts with "$" or "@".
- The command contains a filespec char like "." or ":" before the first word separator ('/', '"', " ", "\t")
- The command starts with a "/" character.
- The first word in the command is a DCL symbol that resolves to a value starting with "$" or "@"

This handles foreign commands and also many UNIX paths, if they contain "." or start with "/", e.g. the perl test harness runs "./perl". For the case of "filespec-looking commands", I had to reset the end-of-word to match " " and "\t" only, so that the UNIX path separator isn't stripped off. I found myself trying to run "." with "/perl" as the first argument. I also had a crashing bug where I didn't reset the word break to the end of the command string if not found when I search the second time (if the command is a single word).

This doesn't solve the question I posed to start this thread, which is finding a way to vfork()/execv() a subprocess that outlives the parent *and* can write to the terminal. However, for Perl's use cases of system() and popen() behavior, it works mostly fine.

The current VMSPIPE path for my_popen() creates read and write mailboxes and then returns a PerlIO object from the mailbox device name. My fast path version creates a UNIX-style PerlIO object from the appropriate file descriptor, so it's using the UNIX I/O code paths, like the generic popen() implementation. So far, the only really strange behavior with my code, and I don't know what to make of this, is it creates a number of empty files named "_VMSVM1$FTA11.DAT" where "_VMSVM1$FTA11" is my SYS$INPUT/SYS$OUTPUT. Are there undocumented circumstances where the C RTL needs to create temp files to implement pipes and vfork/execv? If so, why isn't it deleting the file afterwards?

Here's a pair of simple test programs I wrote to see how pipes behave. The only DECC$ option that seems to matter is DECC$STREAM_PIPE. With it enabled, the individual writes are buffered into reads of 128 to 512 bytes, more or less. On Linux, it depends on timing, but is more likely to read the entire 1024-byte buffer. Setting DECC$PIPE_BUFFER_SIZE and DECC$PIPE_BUFFER_QUOTA made no difference to VMS buffering. Without DECC$STREAM_PIPE enabled, each write() turns into a separate 14-byte read(). I always see UNIX-style newline behavior (a single "\n" at the end of the stream).

/* testpipe.c */
#define _USE_STD_STAT 1

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>

int main() {
char *argv[] = { "./pipechild", NULL };
int pipefds[2];

assert( pipe(pipefds) == 0 );

int savedfd;

assert( (savedfd = dup(1)) > 2);
assert( close(1) == 0);
assert( dup2(pipefds[1], 1) == 1);
assert( close(pipefds[1]) == 0);

int pid = vfork();
if (pid == 0) {
execv(argv[0], argv);
_exit(-1);
} else if (pid < 0) {
perror("vfork failure");
exit(EXIT_FAILURE);
}

assert( close(1) == 0);
assert( dup2(savedfd, 1) == 1);
assert( close(savedfd) == 0 );

struct stat statbuf;
assert( fstat(pipefds[0], &statbuf) == 0);

printf("read pipe mode 0%o: S_ISREG = %d S_ISFIFO = %d\n",
statbuf.st_mode, S_ISREG(statbuf.st_mode),
S_ISFIFO(statbuf.st_mode));

char buf[1024];
ssize_t count;
while ((count = read(pipefds[0], buf, 1024)) > 0) {
printf("read %d bytes: '%-.*s'\n", (int) count, (int) count, buf);
for (int i = 0; i < count; i++) {
if (buf[i] == '\n')
printf("\\n at buf[%d]\n", i);
else if (buf[i] == '\r')
printf("\\r at buf[%d]\n", i);
}
}
if (count < 0)
printf("final errno: %d\n", errno);

assert( close(pipefds[0]) == 0);
}

/* pipechild.c */
#include <stdio.h>
#include <unistd.h>

int main() {
const char hello[] = "Hello, world!\n";
for (int i = 0; i < 200; i++)
write(1, hello, sizeof(hello) - 2);

write(1, hello, sizeof(hello) - 1);
}

Note that I wrote the example in such a way that it works in VMS and UNIX. I'll add to the thread if I discover any more anomalies.

Regards,
Jake Hamby

Re: Unable to replace LIB$SPAWN with vfork/execv

<01f27348-aeeb-42e0-9a1d-75d77cb6d949n@googlegroups.com>

  copy mid

https://www.novabbs.com/computers/article-flat.php?id=30883&group=comp.os.vms#30883

  copy link   Newsgroups: comp.os.vms
X-Received: by 2002:a05:620a:8ec4:b0:773:f2a0:fda5 with SMTP id rg4-20020a05620a8ec400b00773f2a0fda5mr116022qkn.4.1698624197944;
Sun, 29 Oct 2023 17:03:17 -0700 (PDT)
X-Received: by 2002:a05:6870:4d02:b0:1dc:7909:91fa with SMTP id
pn2-20020a0568704d0200b001dc790991famr5397497oab.2.1698624197578; Sun, 29 Oct
2023 17:03:17 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.os.vms
Date: Sun, 29 Oct 2023 17:03:17 -0700 (PDT)
In-Reply-To: <dafd88bc-36da-4293-bcf2-40d5e60052e6n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=2600:1700:46b0:abc0:25b9:97a4:b90f:6cf0;
posting-account=OGFVHQoAAAASiNAamRQec8BtkuXxYFnQ
NNTP-Posting-Host: 2600:1700:46b0:abc0:25b9:97a4:b90f:6cf0
References: <58ca2e43-cbce-4f16-a508-02740817e711n@googlegroups.com> <dafd88bc-36da-4293-bcf2-40d5e60052e6n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <01f27348-aeeb-42e0-9a1d-75d77cb6d949n@googlegroups.com>
Subject: Re: Unable to replace LIB$SPAWN with vfork/execv
From: jake.ha...@gmail.com (Jake Hamby (Solid State Jake))
Injection-Date: Mon, 30 Oct 2023 00:03:17 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
 by: Jake Hamby (Solid St - Mon, 30 Oct 2023 00:03 UTC

On Sunday, October 29, 2023 at 2:27:28 PM UTC-7, Jake Hamby wrote:
> On Saturday, October 28, 2023 at 12:59:29 PM UTC-7, Jake Hamby wrote:
> >
> > So I don't see any way for me to replicate the behavior of putting my own process into the background, as lib$spawn() does, using vfork/exec. Is there any way to do this, or is calling lib$spawn() directly the only way to get the behavior of a subprocess that can outlive the parent and also still write to the terminal?
> After spending quite a bit more time on the problem, I finally have an initial version of a "fast path" for VMS Perl that can use vfork()/execv() under conditions that I know are safe:
>
> - The command starts with "$" or "@".
> - The command contains a filespec char like "." or ":" before the first word separator ('/', '"', " ", "\t")
> - The command starts with a "/" character.
> - The first word in the command is a DCL symbol that resolves to a value starting with "$" or "@"

Here's a link to the git commit I just pushed with my first pass at a fast path for VMS Perl to use vfork()/execv() instead of lib$spawn for running images (including foreign commands):

https://github.com/jhamby/vms-perl5/commit/c152d61306b38e997af26f39481f3837020f39ad

I'm looking at the test case failures and the "%SYSTEM-F-ACCVIO, access violation, reason mask=04" messages I'm getting when running the test harness, as well as some test cases now that are hanging that I have to kill to get the test to continue. Still, I'm quite happy that I was able to condense my investigation into a working prototype that's straightforward, only touches vms/vms.c, and leaves the existing code functional.

Regards,
Jake Hamby

1
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor