agarsha has asked for the wisdom of the Perl Monks concerning the following question:

I am writing an abstraction layer for a Database/OS/System monitoring tool that is going to run on OpenVMS/Windows/UNIX(es).

One tricky piece that I will rub up against shortly is the inability to "fork()" with OpenVMS. (This I find quite crippling, now that I have begun to think UNIX-process-management-style.)

I want to fire off some time-consuming (Order{min}) tasks and I don't want to block on them... but, I will need to get their output.

On UNIX/Win, I am able to fork off some jobs and select on the reading end of their pipe(s) to see when the children are ready to talk.

On OpenVMS???, I am envisioning an ugly hack such as:

--Parent opens temp file (using File::Temp),

--Parent writes a perl script to the file (using Data::Dumper to dump objects into evals, etc.),

--Parent uses System() to submit the perl scripts to OpenVMS "Batch" for detached exec,

--Parent opens listening AF_INET (or preferably AF_UNIX if it works) Socket,

--Batch child does its stuff, then connects to Parent via socket, says its piece, and dies.

Comments? Better ideas? Code snippets? Anyone ever had to emulate forking with OpenVMS? Or tackle problem with completely different approach? Anyone ever written a tcp/ip server for VMS?... How the heck did you do it without forking any procs??

Replies are listed 'Best First'.
Re: fork() emulation hack for OpenVMS
by Elian (Parson) on Mar 09, 2003 at 17:56 UTC
    Generally on VMS the way things like this are done is via nonblocking pending locks with callback ASTs on lock aquisition, or monitoring mailboxes for notifications from spawned subprocesses.

    VMS fully supports tying the input and output handles to a spawned subprocess simultaneously, though I don't think anyone's gotten around to adding it to VMS perl (The infamous open FOO, "| process |" that doesn't work on Unix).

    Probably the right thing to do is to spawn off subprocesses with normal magic open capturing the output of the child process and monitor the return filehandle. Or you could use a threaded perl, I suppose, if you don't want to do that.

      Since I am already going to have to have the dreaded:

      elsif ( $os =~ /OpenVMS/ ) {# Do something VMS style}

      I am open to doing things completely vms-style for VMS; I suppose that since Perl is written on Unix and ported to VMS, that none of the mailbox api, nor nonblocking_lock/callback stuff is exposed.

      I will have to sniff around for pre-compiled Modules/libs, if you happen to have any mods in-mind, let me know. I will hit google for them with or without response. If no pre-compiled available, I'll have to look into Compaq C compiler acquistion (big-$$$).

      Do you happen to know if mailbox/nonblocking_lock->callback stuff is available via DCL? If so, will see if one of my more VMS savvy co-workers can help me put some stuff together for call-out/cheap-exposure-to-perl.

      Comments: Don't trust threaded perl yet + have a bunch of legacy multi-proc code; Don't think I can do non-blocking select on pipes with VMS, so the magic open is a no-go.

      Thanks for your kind/timely response. --adam

      How does VMS handle the buffering issues?

      I mean, how do you handle the situation where a child process is waiting on input while you are waiting on output?

        Shrug. Haven't written any of the code yet for VMS. Probing right now. "select" DOES work in the normal fashion for sockets... just not pipes/filehandles (according to documentation-that-I-can't-find-right-now).

        Looks like "alarm" is supported :)

        --adam

        Generally you don't do that. The paradigm is different.

        Since all of VMS' I/O is potentially asynchronous (and the cluster locking mechanism is considered I/O, of a sort) and you can attach a custom callback and one piece of custom data to each I/O request, as well as wait for one of a set of general "event done" bits to be set. What's generally done is either:

        • Your callback routine initiates the next stage of the task. This is common in bulk copy code such as the VMS backup program--each completed read request has an AST that initiates a write request for the data read, and each completed write request initiates a read for the next chunk. Get a few of these in flight simultaneously and it's easy to get a lot of throughput.
        • Your callback inserts a chunk of data into an AST/interrupt/threadsafe queue (and the system has these) and pings the "event done" bit, at which time the mainline code wakes up, drains the queue, then goes back to sleep waiting on the bit again. This is something like select, only sucks much less.
        The whole "waiting for input & output & stalling" case generally doesn't arise since there's no sync I/O going on. Unfortunately it is a bit more complex than plain sync I/O.