Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

What am I missing? (How to spawn DOS programs.)

3 views
Skip to first unread message

Charles Cruden

unread,
Sep 21, 2000, 3:00:00 AM9/21/00
to
I'm trying to get a multi-process daemon/monitoring type program
working under OS/2. Because of OS/2's interesting calling
requirements (you can't spawn multiple processes and monitor their
return values if they're of different types), I've split things into a
main daemon and several small clients whose only job is to spawn
programs. The basics seem to work, but the DOS programs I'm spawning
are running into some REALLY weird problems. (e.g. Trying to
HSTART.EXE another OS/2 program from one of those DOS sessions
eventually causes OS/2 to say it's "out of resources" trying to run
the program. On another machine, the modem won't work properly: at a
certain point, accessing it causes the DOS session to disappear.)
I've tried to find a problem with the way I'm calling DosStartSession,
but I can't. Can someone illuminate me? What am I doing wrong?

(The client is being called with the program/argmuents starting at
argv[3]. Command contains all the commandline options for the
program, but not the program itself. argv[2] contains various options
for spawning the program: f - spawn in the foreground, b - spawn in
the background, d - use default, D - DOS session, O - OS/2 session, x
- start maximized, n - start minimized.)

...
STARTDATA SD;
HQUEUE Q;
char QueueName[50] = "\\QUEUES\\BBSD";
PID PID;
ULONG SID;

memset(&SD, 0, sizeof(STARTDATA));
SD.Related = 1;
SD.PgmName = argv[3];
SD.PgmInputs = Command;
SD.PgmControl = SSF_CONTROL_MINIMIZE;
SD.Length = 50;
p = argv[2];
while (*p) {
switch (*p) {
case 'f':
SD.FgBg = 0;
break;

case 'b':
SD.FgBg = 1;
break;

case 'd':
SD.SessionType = 7;
break;

case 'D':
SD.SessionType = 4;
break;

case 'O':
SD.SessionType = 1;
break;

case 'o':
SD.SessionType = 2;
break;

case 'x':
SD.PgmControl |= SSF_CONTROL_MAXIMIZE;
SD.PgmControl &= ~SSF_CONTROL_MINIMIZE;
break;

case 'n':
SD.PgmControl |= SSF_CONTROL_MINIMIZE;
SD.PgmControl &= ~SSF_CONTROL_MAXIMIZE;
break;
}
p++;
}

strcat(QueueName, argv[1]);
if (!(rc = DosCreateQueue(&Q, 0, QueueName))) {
SD.TermQ = QueueName;

if (!(rc = DosStartSession(&SD, &SID, &PID))) {
REQUESTDATA RD;
ULONG Length;
void *Data;
BYTE Priority;

PIDArray[PIDOffset].PID = PID;
PIDArray[PIDOffset].Spawns++;
if (!DosReadQueue(Q, &RD, &Length, &Data, 0, 0, &Priority, 0))
{
DosStopSession(0, SID);
DosFreeMem(Data);
DosCloseQueue(Q);
DosSleep(1000);
}
} else {
DosCloseQueue(Q);
PIDArray[PIDOffset].PID = -rc;
return rc;
}
} else {
PIDArray[PIDOffset].PID = -rc;
return rc;
}


Ilya Zakharevich

unread,
Sep 21, 2000, 10:02:45 PM9/21/00
to
[A complimentary Cc of this posting was sent to Charles Cruden
<som...@somewhere.com>],
who wrote in article <8vbjsssro7bm89oc5...@4ax.com>:

> I'm trying to get a multi-process daemon/monitoring type program
> working under OS/2. Because of OS/2's interesting calling
> requirements (you can't spawn multiple processes and monitor their
> return values if they're of different types),

What makes you think so? It is easy. With EMX it is even automatic...

> I've tried to find a problem with the way I'm calling DosStartSession,
> but I can't. Can someone illuminate me? What am I doing wrong?

It looks like you are using C. Why do you want to use API calls
instead of CRT calls?

Ilya

Charles Cruden

unread,
Sep 22, 2000, 3:00:00 AM9/22/00
to
On 22 Sep 2000 02:02:45 GMT, il...@math.ohio-state.edu (Ilya
Zakharevich) wrote:

>[A complimentary Cc of this posting was sent to Charles Cruden
><som...@somewhere.com>],
>who wrote in article <8vbjsssro7bm89oc5...@4ax.com>:
>> I'm trying to get a multi-process daemon/monitoring type program
>> working under OS/2. Because of OS/2's interesting calling
>> requirements (you can't spawn multiple processes and monitor their
>> return values if they're of different types),
>
>What makes you think so? It is easy.

Try it. :)

>With EMX it is even automatic...

I can guarantee you it isn't. Read the specs carefully: I want to be
able to 1) spawn multiple processes from one parent, 2) monitor their
status and 3) spawn different process types. (The parent is an OS/2
process: the children can be OS/2 or DOS.) DosStartSession allows 3)
and either 1) or 2), but not both. DosExecPgm allows 1) and 2) but
not 3). There are no other ways to launch programs. Those
limitations are passed on to the CRT functions, regardless of
compiler. Either way, that's not the point....

>> I've tried to find a problem with the way I'm calling DosStartSession,
>> but I can't. Can someone illuminate me? What am I doing wrong?
>
>It looks like you are using C. Why do you want to use API calls
>instead of CRT calls?

So I can control how the programs are spawned.
(Foreground/background, minimized/maximized.) You can't do that with
spawn* functions.


Shaun Tancheff

unread,
Sep 22, 2000, 3:00:00 AM9/22/00
to
On Thu, 21 Sep 2000 01:02:21 -0600, Charles Cruden
<som...@somewhere.com> wrote:

Since you have the PID you need to use

/* Function Prototypes */
/* int DosQProcStatus( qsPtrRec_t *, int ); */
/* DosQProcStatus() = DOSCALLS.154 */
USHORT APIENTRY16 DosQProcStatus(PVOID pBuf, USHORT cbBuf);

/* DosQuerySysState = DOSCALLS.368 */
APIRET APIENTRY
DosQuerySysState(ULONG func, ULONG par1, ULONG pid,
ULONG _reserved_, PVOID buf, ULONG bufsz);

in order to monitor the process(es) in an active fasion.

pid = LaunchProgram(dosPmVio, fgBg, minMaxNormal, argv)
do
stuff
while isAlive(pid)

BTDT, HTH

>I'm trying to get a multi-process daemon/monitoring type program
>working under OS/2. Because of OS/2's interesting calling
>requirements (you can't spawn multiple processes and monitor their

>return values if they're of different types), I've split things into a
>main daemon and several small clients whose only job is to spawn
>programs. The basics seem to work, but the DOS programs I'm spawning
>are running into some REALLY weird problems. (e.g. Trying to
>HSTART.EXE another OS/2 program from one of those DOS sessions
>eventually causes OS/2 to say it's "out of resources" trying to run
>the program. On another machine, the modem won't work properly: at a
>certain point, accessing it causes the DOS session to disappear.)

>I've tried to find a problem with the way I'm calling DosStartSession,
>but I can't. Can someone illuminate me? What am I doing wrong?
>

http://shaun.tancheff.com/ /?/ -_-
:-) shaun ;-] sh...@tancheff.com (Shaun Tancheff) .sigs freed

Ilya Zakharevich

unread,
Sep 22, 2000, 3:00:00 AM9/22/00
to
[A complimentary Cc of this posting was sent to Charles Cruden
<som...@somewhere.com>],
who wrote in article <mc8mss0h2pslit28o...@4ax.com>:

> >What makes you think so? It is easy.
>
> Try it. :)

I did. See Perl.

> >With EMX it is even automatic...
>

> I can guarantee you it isn't. Read the specs carefully: I want to be
> able to 1) spawn multiple processes from one parent, 2) monitor their
> status and 3) spawn different process types. (The parent is an OS/2
> process: the children can be OS/2 or DOS.) DosStartSession allows 3)
> and either 1) or 2), but not both. DosExecPgm allows 1) and 2) but
> not 3). There are no other ways to launch programs. Those
> limitations are passed on to the CRT functions, regardless of
> compiler. Either way, that's not the point....

As I said: with EMX it is automatic. You are using OS/2 API instead
of standard C calls, like wait() etc.

> >It looks like you are using C. Why do you want to use API calls
> >instead of CRT calls?
>

> So I can control how the programs are spawned.
> (Foreground/background, minimized/maximized.) You can't do that with
> spawn* functions.

Of course you can. At least minimized/maximized (but probably
foreground/background too, do not have the docs at hand).

Ilya

Charles Cruden

unread,
Sep 22, 2000, 3:00:00 AM9/22/00
to
On 22 Sep 2000 19:58:44 GMT, il...@math.ohio-state.edu (Ilya
Zakharevich) wrote:

>[A complimentary Cc of this posting was sent to Charles Cruden
><som...@somewhere.com>],

>who wrote in article <mc8mss0h2pslit28o...@4ax.com>:


>> >What makes you think so? It is easy.
>>

>> Try it. :)
>
>I did. See Perl.

Fine, show me the C code which lets me do it and I'll go from
there....

>> >With EMX it is even automatic...
>>

>> I can guarantee you it isn't. Read the specs carefully: I want to be
>> able to 1) spawn multiple processes from one parent, 2) monitor their
>> status and 3) spawn different process types. (The parent is an OS/2
>> process: the children can be OS/2 or DOS.) DosStartSession allows 3)
>> and either 1) or 2), but not both. DosExecPgm allows 1) and 2) but
>> not 3). There are no other ways to launch programs. Those
>> limitations are passed on to the CRT functions, regardless of
>> compiler. Either way, that's not the point....
>
>As I said: with EMX it is automatic. You are using OS/2 API instead
>of standard C calls, like wait() etc.

I'm using OS/2 API calls because any CRT functions are based on OS/2
API calls, EMX's included. Have you actually tried spawn*'ing a DOS
program in EMX? It doesn't work: you get an "invalid executable file
format".

e.g....
#include <process.h>
#include <stdio.h>

void main () {
int PID;

printf ("Running test.exe.\n");
PID = spawnl(P_NOWAIT, "c:\\4dos\\4dos.com", "c:\\4dos\\4dos.com");
if (PID < 0)
perror(NULL);
}

Compiled with EMX produces:

g:\emx> test.exe
Running test.exe.
Invalid executable file format.

g:\emx>

>> >It looks like you are using C. Why do you want to use API calls
>> >instead of CRT calls?
>>

>> So I can control how the programs are spawned.
>> (Foreground/background, minimized/maximized.) You can't do that with
>> spawn* functions.
>
>Of course you can. At least minimized/maximized (but probably
>foreground/background too, do not have the docs at hand).

You're assuming (for some reason) that I'm using EMX. I'm not: I'm
using Watcom C/C++. Minimized/maximized aren't POSIX switches for
spawn*, so they're not supported. Even EMX doesn't support
foreground/background. When you want full control of what you're
doing, the only way to do it is the API functions....


Marty

unread,
Sep 25, 2000, 1:55:21 AM9/25/00
to
Charles Cruden wrote:
>
> I'm using OS/2 API calls because any CRT functions are based on OS/2
> API calls, EMX's included. Have you actually tried spawn*'ing a DOS
> program in EMX? It doesn't work: you get an "invalid executable file
> format".

Two thoughts:

1] Look at the Dos*Session OS/2 API calls in the Control Program reference.
2] Perhaps your Watcom DOS executable relies on a DOS extender, such as
DOS4GW. Make sure it can locate DOS4GW in the PATH of the DOS environment or
execute DOS4GW.EXE directly with the full path to your executable as a
parameter.

Shaun Tancheff

unread,
Sep 25, 2000, 3:00:00 AM9/25/00
to
On Thu, 21 Sep 2000 01:02:21 -0600, Charles Cruden
<som...@somewhere.com> wrote:

>I'm trying to get a multi-process daemon/monitoring type program
>working under OS/2. Because of OS/2's interesting calling
>requirements (you can't spawn multiple processes and monitor their
>return values if they're of different types), I've split things into a
>main daemon and several small clients whose only job is to spawn
>programs. The basics seem to work, but the DOS programs I'm spawning
>are running into some REALLY weird problems. (e.g. Trying to
>HSTART.EXE another OS/2 program from one of those DOS sessions
>eventually causes OS/2 to say it's "out of resources" trying to run
>the program. On another machine, the modem won't work properly: at a
>certain point, accessing it causes the DOS session to disappear.)
>I've tried to find a problem with the way I'm calling DosStartSession,
>but I can't. Can someone illuminate me? What am I doing wrong?

"out of resources" implies you are starting 'related' sessions.

This means you are using up file handles that you don't have to
spare. (OS/2 is pretty stingy with per-process file handles IMO)
Soltion:
- Increase # of file handles
- Start them un-releated so each sub-process gets a new
set of handles.

Ilya Zakharevich

unread,
Sep 25, 2000, 3:00:00 AM9/25/00
to
[A complimentary Cc of this posting was sent to Marty
<mam...@stny.rr.com>],
who wrote in article <39CEEBBF...@stny.rr.com>:

[Replying to this message, since the parent have not arrived here yet]

> > I'm using OS/2 API calls because any CRT functions are based on OS/2
> > API calls, EMX's included.

This is exactly my point: EMX uses the API, and *can* do what you ask
for. Ergo: APIs can do what you ask for. But this is tricky indeed.
Better use EMX calls, which have the trickery hidden in EMX.DLL (see
(names from memory) src/os2/process.c and src/os2/signal.c).

> Have you actually tried spawn*'ing a DOS
> > program in EMX? It doesn't work: you get an "invalid executable file
> > format".

Did not you forget to specify the P_SESSION flag?

Ilya

Simon Bowring

unread,
Sep 25, 2000, 3:00:00 AM9/25/00
to
>Because of OS/2's interesting calling requirements (you can't spawn
>multiple processes and monitor their return values if they're of
>different types),

I know that DosStartSession() is a real *bitch*, but what makes you say
the above? I don't recall that behaviour, but it was several years ago
since I wrote any code that uses DosStartSession(). As you correctly say/imply,
DosStartSession() is the OS/2 primitive for implementing all forms
of process/session starting - its the only way of
controlling all aspects of a session's behaviour - you just can't do
everything with the ANSI and unix/posix-alike calls in EMX(!), and as
such *I believe* it must be able to implement all the behaviours you
require!

The program in which I used DosStartSession() the most, was an
advanced scheduler that had multiple threads (one for each of several
configurable "scheduler queues" which I called a "sequencer").

Each sequencer thread could start child sessions, but there was only
one single termination handler thread and single global termination
queue for all for child session completion values [Is this the
key diffrerence beteeen my code and yours?]

I will attempt to identify what I did differently to your code, but
it's not that easy...

At program startup, I created a single (global) OS/2 queue to receive all
"child" session termination values (this appears to be the main
difference between my code and yours - I had one global queue for *all*
child sessions!).

Next I created a single termination handler thread which looped around a
blocking DosReadQueue() of the termination queue. When this successfully
returned, a termination value (session id and program return code) was
read from the queue, and the data packet containing it had to be
DosFreeMem()ed.

When starting a new session, I *defaulted* the STARTDATA fields as follows:

// Ensure STARTDATA structure is entirely zeroed out
memset(&pWorker->sd, '\0', sizeof(pWorker->sd));
pWorker->sd.Length = sizeof(pWorker->sd);
pWorker->sd.PgmTitle = NULL;
pWorker->sd.PgmName = NULL;
pWorker->sd.PgmInputs = NULL;
pWorker->sd.Related = SSF_RELATED_CHILD; // Important for sess ctrl.
pWorker->sd.FgBg = SSF_FGBG_BACK; //SSF_FGBG_FORE;
pWorker->sd.TraceOpt = SSF_TRACEOPT_NONE;
pWorker->sd.TermQ = Glob.pszSeqTermQ; // Sequencer's term Q name
pWorker->sd.Environment = NULL;
pWorker->sd.InheritOpt = SSF_INHERTOPT_PARENT; // Important for current dir
pWorker->sd.SessionType = SSF_TYPE_DEFAULT;
pWorker->sd.IconFile = NULL;
pWorker->sd.PgmHandle = 0;
pWorker->sd.PgmControl = SSF_CONTROL_VISIBLE;

Obviously some of the above (especially SessionType, and PgmName and PgmInputs
etc) got overriden later [note DosStartSession(), doesn't look at the
PATH environment variable, so I had to program this functionality
"manually" using DosSearchPath()]. Also my code dynamically allocated
all "buffees" like PgmTitle, PgmName and PgmInputs etc and explicity freed
them in the termination handler. I also couldn't find a way to set a
child session's working directory without:

1. Setting sd.InheritOpt = SSF_INHERTOPT_PARENT
2. Grabbing a "directory" mutex [becvause I had multiple threads that
could DosStartSession(), yet the process can only have a single
cwd at a time]
3. Changing to the required woring dir
4. DosStartSession()
5. changing back to the original dir
6. Freeing the "directory" mutex


BTW: My code never called DosStopSession()!

Hope this may be of some help!

Simon Bowring
Senior Software Engineer
MPC Data Limited

0 new messages