Having trouble understanding the man page for VkSubProcess

IRIX/Nekoware development, porting and related topics.
Forum rules
Any posts concerning pirated software or offering to buy/sell/trade commercial software are subject to removal.
User avatar
jimmer
Donor
Donor
Posts: 466
Joined: Tue Oct 12, 2004 3:54 pm
Location: London, Ingerlund

Having trouble understanding the man page for VkSubProcess

Unread postby jimmer » Sat Sep 16, 2017 4:58 pm

Hey All,

Feeling a little stupid - maybe some kind soul can help out.

I'm trying to spawn an external process like 'tar' from a Motif GUI whilst getting ongoing updates from the spawned process.

Messing around with sgitcl has got me some ok-ish results. However, the tclMotif UI locks-up as it waits for the external command to complete. To feel somewhat less stupid, I've spent some time refreshing my memory about pipe/fork/exec/waitpid and have been successful in launching processes from a toy CLI C programme.

A million years ago when I wrote my 'cdrecord' Motif front-end thing, I moved the whole traditional pipe/fork/exec malarkey into a class and 'hoped for the best'. It worked, but of course suffered from the same UI locking-up issues, which I camouflaged by posting a modal progress dialog for the duration of the burn. This time around I'm trying to understand how to use VkSubProcess() and hopefully gain some more flexibility and a better understanding of things. Together with VkPipe and VkInput, VkSubProcess should make the pain go away by raising VkCallback events when stuff happens on the relevant file descriptors. Unfortunately, there's no available example code and I'm having a hard time understanding how to code things just by reading the man page for VkSubProcess.

I tried the following:

Code: Select all

VkSubProcess *p = new VkSubProcess();
p->create("ls", TRUE, FALSE);
p->run();


But that gives me compilation errors and a headache after trying various permutations :(

So, before I waste weeks banging my head on this and then giving up, I figured I'd ask for directions instead. A bit of code that spawns something through VkSubProcess would be ideal, I'll try and figure out the rest from there.

Thanks muchly :)

J

mbeauchesne
Donor
Donor
Posts: 4
Joined: Mon Jun 09, 2003 7:41 am
Location: NH, USA

Re: Having trouble understanding the man page for VkSubProcess

Unread postby mbeauchesne » Sat Sep 16, 2017 5:47 pm

I don't have any actual experience with this class, but after trying to make sense of the header file, it looks like you need to dereference the pointer to the VkSubProcess to get at the VkSubProcessRep object that seems to be created by the VkSubProcess constructor, as the VkSubProcessRep object is actually where the create and run functions appear to exist. The VkSubProcess class itself doesn't seem to define all that much of an interface.

So by writing it as follows, I was at least able to get a simple example program to compile. Though I'm not sure if this is the intended way for it to be used. Hopefully it at least helps you make some progress.

Code: Select all

VkSubProcess *p = new VkSubProcess();
(*p)->create("ls", TRUE, FALSE);
(*p)->run();
:O3x02L: :Tezro: :Fuel: :Octane2: :O2+: :Indigo2IMP: :Indy:

User avatar
vishnu
Donor
Donor
Posts: 3174
Joined: Sun Mar 18, 2007 3:25 pm
Location: Minneapolis, Minnesota USA

Re: Having trouble understanding the man page for VkSubProcess

Unread postby vishnu » Mon Sep 18, 2017 11:15 am

I'll take a look at this when I get home tonight. The reason Viewkit's manpages are such total crap is because it was never supposed to be coded by hand, developers were supposed to use rapidapp, and then when they deprecated rapidapp they were supposed to switch to BX Pro. At that point SGI handed BX Pro off to ICS, which (supposedly) still supports and markets it. I bought the Linux version from them decades ago...
Project:
Temporarily lost at sea...
Plan:
World domination! Or something...

:Tezro: :Octane2:

User avatar
jimmer
Donor
Donor
Posts: 466
Joined: Tue Oct 12, 2004 3:54 pm
Location: London, Ingerlund

Re: Having trouble understanding the man page for VkSubProcess

Unread postby jimmer » Thu Sep 21, 2017 10:08 am

Thanks guys for taking a look at this - I'm away from the IRIX boxen for a few days, but will continue my efforts when I get back.

User avatar
vishnu
Donor
Donor
Posts: 3174
Joined: Sun Mar 18, 2007 3:25 pm
Location: Minneapolis, Minnesota USA

Re: Having trouble understanding the man page for VkSubProcess

Unread postby vishnu » Fri Sep 22, 2017 10:34 pm

Just for funzies I dled the latest version of BX Pro from the ICS website (version 6.2), to see if it has support for VkSubProcess objects; it doesn't look like it has any. Hope to look into this a bit more this weekend, I find the thought of having an OO interface into Unix processes to be very nerdly intriguing... :mrgreen:
Project:
Temporarily lost at sea...
Plan:
World domination! Or something...

:Tezro: :Octane2:

User avatar
jimmer
Donor
Donor
Posts: 466
Joined: Tue Oct 12, 2004 3:54 pm
Location: London, Ingerlund

Re: Having trouble understanding the man page for VkSubProcess

Unread postby jimmer » Sun Sep 24, 2017 8:26 am

I've done some more reading. It seems that in wanting/needing to spawn an external program and then wanting to communicate with it, I'm running into a very old Xlib/Xt problem rooted in the event-driven nature of X11.

As I understand it now, X11 applications deal with 'window system' events by running a single endless while-loop at the core of any programme. In this loop each X11 event is dispatched into the programme and dealt with appropriately. If you add another loop someplace in your application you are in fact 'holding-up' the looping of the main event-loop and this is why your UI locks-up. In other words, you cannot have some other loop waiting on external data/inputs outside of the X11 event queue.

With pure Xlib the solution seems to be to add a select() in the main event-loop to handle the inputs/data from your external programme. With Xt there is XtAppAddInput() which serves the same purpose, but hides the details of the select(). I suspect that Xt implements this with it's own select()-based mechanism. Of course ViewKit tries hard to hide all the X11 initialisation and main event-loop handling stuff from well-meaning incompetents like myself. Ironically, this made it difficult to understand what was going on in the first place :)

I'm sure The-Forum-Members-Who-Know-Stuff are having a little giggle at me for discovering all of this 30yrs late, but hey, better late than never.
:Fuel: redbox 800Mhz 4Gb V12
:O2: bluebox 200Mhz 256Mb AV1+O2Cam

User avatar
vishnu
Donor
Donor
Posts: 3174
Joined: Sun Mar 18, 2007 3:25 pm
Location: Minneapolis, Minnesota USA

Re: Having trouble understanding the man page for VkSubProcess

Unread postby vishnu » Sun Sep 24, 2017 9:07 pm

jimmer wrote:As I understand it now, X11 applications deal with 'window system' events by running a single endless while-loop at the core of any programme.
Not to get all nit-picky on you but it's actually a for loop... ;)

What a lot of people do is copy the source code to XtAppMainLoop and add their own code like this:

Code: Select all

void XtAppMainLoop(XtAppContext app_context)
{
    XEvent event;
   
    for(;;)
    {
        XtAppNextEvent(app_context, &event);
       
        /* Your code here; intercept keystrokes etc. */
       
        XtDispatchEvent(&event);
    }
}


There are a bunch of ways of doing background processing with Xt, so that the user interface stays responsive while your code is running. For example work procedures (you write a work procedure callback using XtAppAddWorkProc) and timers (you write a timer callback function with XtTimerCallbackProc), any X/Xt/Motif book will have plenty of example code showing how to use these. Undoubtedly we've all got a crapton of Motif books. Or am I the only one... ;)

What I always do when I've got a huge loop running is to call a function each time through the loop that updates the user interface. For example in my blackjack simulator (here: viewtopic.php?f=7&t=16729202) I have a loop that deals a million hands of blackjack, but for each hand that's dealt I call the setValues() function, which uses the Xt function core_class.expose() to force the user interface to update (to use core_class.expose, which is one of my all time favorite Xt functions, you have to include the private header IntrinsicP.h because apparently end-user programmers aren't supposed to use one of Xt's most useful functions, go figure. That's why the "X Windows Disaster" chapter of the Unix Hater's Handbook is my favorite chapter). :twisted:

Anyway I'm also having a hell of a time getting VkSubProcess to compile, using both Viewkit 1.3.1 on my Linux box and Viewkit 2.1 on my Octane2, the compilers are telling me it doesn't have a run() member function but both the header file and the manpage say it does. I assume I'm doing something stupid but honestly I don't see what, maybe it just never got implemented right and we're the only ones who've noticed... :shock:
Project:
Temporarily lost at sea...
Plan:
World domination! Or something...

:Tezro: :Octane2:

User avatar
jimmer
Donor
Donor
Posts: 466
Joined: Tue Oct 12, 2004 3:54 pm
Location: London, Ingerlund

Re: Having trouble understanding the man page for VkSubProcess

Unread postby jimmer » Mon Sep 25, 2017 12:08 pm

Progress. Of a sort.

Code: Select all

#include <unistd.h>

#include <iostream>
using namespace std;

#include <Vk/VkApp.h>
#include <Vk/VkInput.h>
#include <Vk/VkProgram.h>
#include <Vk/VkSubProcess.h>

void cb_exit(VkCallbackObject *obj, void *clientData, void *callData) {

   cout << "spawned cmd exited." << endl;
}

void cb_output(VkCallbackObject *obj, void *clientData, void *callData) {

   VkInput *calldata = (VkInput *) callData;

   char buf[128];
   int n = read(calldata->fd(), buf, 127);
   buf[n] = 0;

   cout << "n: "   << n   << endl;
   cout << "buf: " << buf << endl;
}

int main(int argc, char *argv[]) {

   VkApp      *app = new VkApp("Test", &argc, argv);
   VkProgram *p   = new VkProgram("ls");

   p->addCallback(VkProgram::exitCallback,   (VkCallbackFunction) &cb_exit  );
   p->addCallback(VkProgram::stdoutCallback, (VkCallbackFunction) &cb_output);

//   VkSubProcess sub_p = p->run();
   cout << "cmd pid: " << p->run()->pid() << endl;

   app->run();
}


This will spawn an external program and fire Vk-style callbacks for stdout and spawned cmd exit events. I'm thinking this is all unbuffered and getting it to be line-buffered would be fab. Also, if you use the intermediate sub_p VkSubProcess object directly as in: sub_p->pid(), the stdout callback goes haywire. However, VkSubProcess is obviously working because when we chain the method calls: p->run()->pid() it works fine.

Obviously, my poor understanding of C++ inheritance syntax and its rules is causing a good deal of my grief here.

J.
:Fuel: redbox 800Mhz 4Gb V12
:O2: bluebox 200Mhz 256Mb AV1+O2Cam

User avatar
vishnu
Donor
Donor
Posts: 3174
Joined: Sun Mar 18, 2007 3:25 pm
Location: Minneapolis, Minnesota USA

Re: Having trouble understanding the man page for VkSubProcess

Unread postby vishnu » Mon Sep 25, 2017 9:21 pm

jimmer wrote:Progress. Of a sort.

Hey, nice! That compiles and runs just fine on my computers (Linux and Octane2).

jimmer wrote:Obviously, my poor understanding of C++ inheritance syntax and its rules is causing a good deal of my grief here.


Uh, I'm not sure why you say that, you haven't inherited anything in that code! :lol:

Probably what you want to do is to derive a class from VkSimpleWindow and add a scrolled text widget to write the output of the subprocesses into, something along the lines of...

Code: Select all

#include <Xm/Text.h>

class jimmerWindow : public VkSimpleWindow
{
public:
    jimmerWindow(const char * name);
    ~jimmerWindow();
    virtual const char * className();
    Widget scrolledText;
};

jimmerWindow::jimmerWindow(const char *name) : VkSimpleWindow(name)
{
    scrolledText =  XmCreateScrolledText (mainWindowWidget(), "scrolledtext", NULL, 0);
    addView(scrolledText);
}

const char* jimmerWindow::className()
{
    return "jimmerWindow";  // Identify this class
}

jimmerWindow::~jimmerWindow()
{
    // Empty
}


You'd have to add access functions to the class that use XmTextSetString and/or XmTextReplaceString to add/replace the text in the widget with the data you get from VkProgram::stdoutCallback, I'll take a look at that tomorrow (it's almost midnight here and I've still got a day job!). :mrgreen:
Project:
Temporarily lost at sea...
Plan:
World domination! Or something...

:Tezro: :Octane2:

User avatar
jimmer
Donor
Donor
Posts: 466
Joined: Tue Oct 12, 2004 3:54 pm
Location: London, Ingerlund

Re: Having trouble understanding the man page for VkSubProcess

Unread postby jimmer » Tue Sep 26, 2017 3:43 am

vishnu wrote:Uh, I'm not sure why you say that, you haven't inherited anything in that code! :lol:


That was me just guessing there might be some sort of inheritance relationship going on between VkProgram and VkSubProcess, or some other bit of C++ I don't fully understand which gives us the 'there's no run() method' error when we try and instantiate a VkSubProcess class directly, or the callbacks-going-haywire error when we don't chain the methods.

vishnu wrote:Probably what you want to do is to derive a class from VkSimpleWindow and add a scrolled text widget to write the output of the subprocesses into, something along the lines of...


Yeah, I left out all the UI aspects to focus on getting the external program spawning stuff going.
:Fuel: redbox 800Mhz 4Gb V12
:O2: bluebox 200Mhz 256Mb AV1+O2Cam

User avatar
vishnu
Donor
Donor
Posts: 3174
Joined: Sun Mar 18, 2007 3:25 pm
Location: Minneapolis, Minnesota USA

Re: Having trouble understanding the man page for VkSubProcess

Unread postby vishnu » Thu Sep 28, 2017 9:08 pm

VkProgram and VkSubProcess appear to do basically the same thing, from the manpage headings:

Code: Select all

NAME
       VkSubProcess, VkSubProcessRep -- Object-oriented interface to a running subprocess

NAME
       VkProgram -- Object-oriented interface to subprogram execution


Not sure what the thinking was with regard to that, but at least VkProgram actually compiles and runs, which is more than you can say for VkSubProcess... :roll:

I just got a quote from ICS for an IRIX license for BX Pro 6.2, $8,995 US... :shock:
Project:
Temporarily lost at sea...
Plan:
World domination! Or something...

:Tezro: :Octane2:

User avatar
jimmer
Donor
Donor
Posts: 466
Joined: Tue Oct 12, 2004 3:54 pm
Location: London, Ingerlund

Re: Having trouble understanding the man page for VkSubProcess

Unread postby jimmer » Fri Sep 29, 2017 5:26 am

9000 USD? Good grief.

I've been looking into the IRIX header of VkSubProcess. The constructor of VkSubProcessRep is a protected member which seems to be a dead giveaway that it's meant to be used in some inherited/overloaded way. VkSubProcess itself is just typedeffed off of this reference-counted abstract base class complex. But, like I've said before, I do not really understand the subtleties of this kind of C++ stuff.

I also looked into the sources of ViewKlass, the opensource version of ViewKit. It doesn't do any of the reference-counting that real ViewKit does and thus its code is much simpler. It seems to be doing what I did last time around: wrapping the classic fork/exec dance in class-member functions.

I'm hoping to bang my head on this stuff some more this weekend.
:Fuel: redbox 800Mhz 4Gb V12
:O2: bluebox 200Mhz 256Mb AV1+O2Cam

User avatar
vishnu
Donor
Donor
Posts: 3174
Joined: Sun Mar 18, 2007 3:25 pm
Location: Minneapolis, Minnesota USA

Re: Having trouble understanding the man page for VkSubProcess

Unread postby vishnu » Fri Sep 29, 2017 12:46 pm

jimmer wrote:9000 USD? Good grief.


I found the invoice from when I bought the Linux version of BX 5 in 1999, $250 US. I'll have to dig out my old Slackware 8 CDs if I ever want to use it again... 8-)

jimmer wrote:I've been looking into the IRIX header of VkSubProcess.


I just read the header, yikes! What sucks is that Doug Young wrote a detailed book on how to use MotifApp, which was the basis for Viewkit, but nothing on how to use Viewkit itself. Well, there's the Viewkit Programmer's Guide, which says not one word about either VkSubProcess or VkProgram. Incidentally, the NASA Vicar program still uses MotifApp and they've written a bunch of new code adding classes and extending the original classes from the book, it's available here:

https://github.com/nasa/VICAR/tree/master/vos/MotifApp

jimmer wrote: I'm hoping to bang my head on this stuff some more this weekend.


I'm to the point where I can actually instantiate VkSubProcess objects, I'll post it when I can get those objects to actually do some of the things the class is supposed to be able to do... :lol:

EDIT: Oops I meant that I had to derive a class from VkSubProcess and instantiate objects from it, I never was able to instantiate VkSubProcess objects directly.
Project:
Temporarily lost at sea...
Plan:
World domination! Or something...

:Tezro: :Octane2:

User avatar
jimmer
Donor
Donor
Posts: 466
Joined: Tue Oct 12, 2004 3:54 pm
Location: London, Ingerlund

Re: Archiver 0.1 - IRIX/IMD GUI for tar.

Unread postby jimmer » Sun Oct 15, 2017 6:09 pm

Spent some more time reading about stuff in the world of C++. Turns out that the whole VkSubProcess thing is an implementation of the Singleton OOP design pattern. The static "create()" fn and the protected constructor are typical of that pattern. Who knew. Anyhow, it gives us the following working code:

Code: Select all

#include <Vk/VkApp.h>
#include <Vk/VkSubProcess.h>

int main(int argc, int argv) {
   
   VkApp *app = new VkApp("Test", &argc , argv);
   VkSubProcess process = VkSubProcessRep::create("ls -al", 1, 1);
   process->run();
   app->run();
}


However, I still havent figured out how to get the right file descriptor out of getStdoutPipe() to feed into a VkInput. This:

Code: Select all

VkPipe *pipe = process->getStdoutPipe();
int fid = &pipe[1];
VkInput *process_output = new VkInput();
process_output->attach(fid, XtInputReadMask);


Doesn't do the trick because I don't seem to be able to get an integer out of pipe[]. But:

Code: Select all

VkPipe *pipe = process->getStdoutPipe();
cout << &pipe[0] << endl;
cout << &pipe[1] << endl;


Seems to be giving file descriptor numbers.

Not knowing my head from my arse in C/C++ is just sooo tiresome :(


Return to “SGI: Development”

Who is online

Users browsing this forum: Google [Bot] and 3 guests