[comp.sys.apollo] suspending processes

danny@idacom.UUCP (Danny Wilson) (12/17/87)

I am aware of the commands to Suspend and Continue processes
using the DS and DC DM commands. However, does anyone
out there know how to do it if a pad to that process 
does not exist?

i.e. How do you suspend a print server running in background
given its process name or UID??

Thanks
Danny Wilson
IDACOM Electronics	alberta!teletron!idacom!danny
			danny@idacom.uucp

holtz@cascade.carleton.CDN (Neal Holtz) (12/18/87)

> Sender:  Danny Wilson <ihnp4!alberta!teletron!idacom!danny@UCBVAX.BERKELEY.EDU>
> 
> i.e. How do you suspend a print server running in background
> given its process name or UID??

By using (even more) undocumented system calls.  Following is a short C
program that does the trick for us:
-------------------------- cut here -------------------------------
/* 
 * will suspend a process, given its UID or name
 *
 * Usage:  suspend  { proc_name | uid }
 *
 * If argument begins with a decimal digit, it is assumed to be a UID, 
 * otherwise it is assumed to be a process name.
 */

#include <stdio.h>
#include "/sys/ins/base.ins.c"
#include "/sys/ins/streams.ins.c"
#include "/sys/ins/proc2.ins.c"
#include "/sys/ins/error.ins.c"

#define PROC_DIR        "`node_data/proc_dir"

typedef union {
    struct {
        time_$clockh_t toc;             /* time of creation */
        short          xxx;             /* what is this? */
        short          node;
    } p1;
    struct {
        unsigned int   high32;
        unsigned int   low32;
    } p2;
} UID_T;


UID_T           puid;
char            procname[64];

std_$call void  proc2_$suspend();


main( argc, argv )
int     argc;
char   *argv[];
{
        int     n;
        status_$t st;

        error_$init_std_format( stream_$errout, "?", *argv[0], (short)strlen(argv[0]) );

        if( (argc<2) || (argc>3) )
                complain(argv[0]);

        puid.high32 = 0;
        puid.low32 = 0;

        if( *argv[1] >= '0' && *argv[1] <= '9' ) {      /* its a UID */
                n = sscanf( argv[1], "%x.%x", &puid.high32, &puid.low32 );
                if( n==0 )
                        complain(argv[0]);
                if( n==1 ) {
                        if( argc==3 )
                               if( sscanf( argv[2], "%x", &puid.low32 ) != 1 )
                                         complain(argv[0]);
                        }
                sprintf( procname, "%08lx.%08lx", puid.high32, puid.low32 );
                }
        else {                                          /* its a process name */
                getprocuid( PROC_DIR, argv[1], &puid );
                sprintf( procname, "%s", argv[1] );
                }
 
        proc2_$suspend( puid, st );

        if( st.all == status_$ok )
               printf("\n******************** Please remember to resume process \"%s\" ********************\n\n", procname );
        else
               error_$std_format( st, "Unable to suspend process \"%la\"%$", procname, (short)strlen(procname) );
 
}

complain( s )
char   *s;
{
        fprintf( stderr, "?(%s) Usage:    %s  { proc_name | uid_high.uid_low | uid_high uid_low}\n", s, s );
        exit( 1 );
}

/*
 * translate a process name to its UID by searching the node proc_dir directory 
 * Apollo directories contain the UID associated with each name (undocumented)
 */

getprocuid( dirname, procname, puid )
char    *dirname;
char    *procname;
UID_T   *puid;
{
        stream_$id_t    sid;
        stream_$sk_t    sk;
        status_$t       st;
        linteger        len;
        stream_$dir_entry_t     dirent, *d;
        char            pname[256], ename[256], *s, *t;

                /* prepare to read the directory */

        stream_$open( *dirname, (short)strlen(dirname), stream_$read, stream_$unregulated,
                     sid, st );
        if( st.all != status_$ok ) {
                error_$std_format( st, "Unable to open directory \"%la\"%$", *dirname, (short)strlen(dirname) );
                exit( 1 );
                }

                /* translate process name to lower case */

        for( t=pname, s=procname; *s != '\0'; s++, t++ )
                if( *s >= 'A' && *s <= 'Z' )
                        *t = *s + 32;
                else
                        *t = *s;
        *t = '\0'; 

                /* search proc_dir for process name */

        do {
                stream_$get_rec( sid, &dirent, sizeof(dirent), d, len, sk, st );
                if( st.code == stream_$end_of_file ) {
                        error_$std_format( status_$ok, "Process \"%la\" not found%$", *procname, (short)strlen(procname) );
                        exit( 1 );
                        }
                if( st.all != status_$ok ) {
                        error_$std_format( st, "Error reading directory \"%la\"%$", *dirname, (short)strlen(dirname) );
                        exit( 1 );
                        }
                if( d->entlen <= 0 || d->entlen > sizeof(d->entname) ) {
                        error_$std_format( status_$ok, "Invalid directory entry in \"%la\"%$" , *dirname, (short)strlen(dirname) );
                        exit( 1 );
                        }
                strncpy( ename, d->entname, d->entlen );
                ename[d->entlen] = '\0';
                if( strcmp(pname,ename) == 0 ) {
                        puid->high32 = d->unused1;      /* this isn't documented, but */
                        puid->low32 = d->unused2;       /*   we know what it is. Heh. Heh. */
                        return;
                        }

            } while( 1 );
}
-------------------------- end cut --------------------------------

rich@eddie.MIT.EDU (Richard Caloggero) (12/18/87)

In article <179@idacom.UUCP> danny@idacom.UUCP (Danny Wilson) writes:
>I am aware of the commands to Suspend and Continue processes
>using the DS and DC DM commands. However, does anyone
>out there know how to do it if a pad to that process 
>does not exist?
>
>i.e. How do you suspend a print server running in background
>given its process name or UID??
>
>Thanks
>Danny Wilson
>IDACOM Electronics	alberta!teletron!idacom!danny
>			danny@idacom.uucp


     A while back, I was poking around in some of the runtime *system*
     libraries and noticed the following calls:
	proc2_$suspend (puid, status); proc2_$resume (puid, status);
	PM_$NAME_TO_PUID (NAME,NAME_LEN, PUID, STATUS); pm_$get_name
	(puid, name,name_len, status); proc2_$quit (puid, status).

All of these calls take arguments of the expected types.

     I do have one favor to ask people out there in netland relating to
     this point.  All of the formentioned calls are, I think,
documented in "Programming With Domain Advanced System Called", order
#008542.  My problem is that we never got this document when we got our
systems.  Also, I am blind, and even if we had a copy, it wouldn't do
me much good. I recently talked to a friend of mine who works at
Apollo, and he claimed that there is no on-line document which contains
this info. Can anyone out there verify this or provide me with such an
on-line document?  Documentation has always been a problem for me, so
any help/advice in this area would be incredibly valuable to me!!
Thanx in advance!!
-- 
						-- Rich (rich@eddie.mit.edu).
	The circle is open, but unbroken.
	Merry meet, merry part,
	and merry meet again.

george@hyper.lap.upenn.edu (George Zipperlen) (12/19/87)

In article <179@idacom.UUCP> danny@idacom.UUCP (Danny Wilson) writes:
>I am aware of the commands to Suspend and Continue processes
>using the DS and DC DM commands. However, does anyone
>out there know how to do it if a pad to that process 
>does not exist?
>
>i.e. How do you suspend a print server running in background
>given its process name or UID??
>
>Thanks
>Danny Wilson
>IDACOM Electronics	alberta!teletron!idacom!danny
>			danny@idacom.uucp

for suspend try (in any shell)
    sigp [ proc_name | -uid xxx.xxx ]   -c 120027  
for continue try
    sigp [ proc_name | -uid xxx.xxx ]   -c 12002b 

I know this doesn't EXACTLY duplicate the effect of the dmcmds 
"ds" and "dc", but it does put the process in a wait state.

BTW I got the numbers from "/sys/ins/fault.ins.c"


--------------------------------------------------------------------------------
George Zipperlen                    george@apollo.lap.upenn.edu
Language Analysis Project           george@hyper.lap.upenn.edu
University of Pennsylvania          Generic Disclaimer
Philadelphia, Pa.                   Cute saying
--------------------------------------------------------------------------------

rees@apollo.uucp (Jim Rees) (12/24/87)

You can use proc_$suspend and resume, which is what the DM uses, but
they are less than ideal.  They do an unconditional suspend at the
proc2 level, which is below all the user space locking.  So if you
manage to suspend some process while it is holding some critical
lock, say the sfcb lock, you're in for trouble.  If you've ever had
the DM say "unable to lock needed resources," this is what's going
on.

A much better way, that uses released interfaces, is to use the
unix SIGSTOP (unfortunate name, not related to fault_$stop) and
SIGCONT signals.  These interact correctly with user space locks.
The proc2 versions should only be necessary if you have some process
that's totally wedged in an inhibited loop, and if you do, you're
going to have to blast it anyway.

"ANIMAL::ERSTAD"@CIM-VAX.HONEYWELL.COM (09/15/88)

One method of suspending a process which works reasonably is to set the
priority of the process to 1/1, starting another process at priority
2/2, and doing a command like "while ((1=1)) do enddo" in the new shell.
This is a little kludgy, but does work.  Although the while process
gets lots of cpu time, it doesn't really interfere with rest of node
operation since there is so little context associated with it.

This especially helps if you have background jobs which require large
amounts of memory - the problem is not usually processor utilization, 
it's that while your thinking about your next keystroke the OS pages
out all of your data and pages in all the background data - to 
process the keystroke requires the reverse to take place before any
action can occur.  It's not really that straightforward, but if you
think of it that way you won't go too wrong.

dbfunk@ICAEN.UIOWA.EDU (David B. Funk) (09/16/88)

There are 2 ways to really suspend a process, a suspend signal and a
(undocumented) suspend system call.

    If a process is given a fault_$suspend_proc signal it will stop
execution until it receives a fault_$continue_proc signal (look
in /sys/ins/fault.ins.{pas,c,ftn} for their definition). To give
one of these signals you will have to use /com/sigp with the "-c"
option. EG: '$ sigp -c 120027 process_151' will cause process_151
to stop execution. In a pst it will be listed as in a Wait state
but a 'tb process_151' will show that it is in a suspend fault
condition.
     WARNING, only a continue signal will take it out of the
suspend. If the process receives some other type of signal first,
such as a stop or quit, the other signal will block the continue
signal and the process is in gridlock and can only be blasted.
So if you have any questions as to what a waiting process is up
to, first do a 'tb' on it. If you see something like:

  $ tb siologin_1
  In System Service "ec2_$wait"
  Called from Diagnostic Frame - process suspend fault (OS/fault handler)
  Called from "GET_IT" line 931
  Called from "SIO_GET" line 964
  Called from "STREAM_$GET_REC" line 150
  Called from "readline" line 67
  Called from "builtin" line 651
  ...

then give that process a "-c 12002b" signal before doing any thing else
to it.
    The DM 'ds' and 'dc' commands use undocumented system calls to suspend
and continue a process. These work in the kernal and actually change the
process manager dispatch status. This will show up in a pst state as 'Susp'.
This is safer as a 'dc' cannot be blocked by another signal but the process
must be continued before it will respond to any signal. IE you will have to
continue it before your stop or kill signals will take effect.

   Dave Funk    dbfunk@icaen.uiowa.edu

dave@jplopto.uucp (Dave Hayes) (09/16/88)

Why not just use "sigp -code <suspend fault>" to suspend a process? 

------------=====<<<<(Dave Hayes)>>>>=====-------------
          dave%jplopto@jpl-mil.jpl.nasa.gov 
          {cit-vax,ames}!elroy!jplopto!dave  

krowitz@RICHTER.MIT.EDU (David Krowitz) (09/16/88)

Apparently, this will suspend the process at the proc1 level, where
it may have some important system resource locked. The DM's DS command
suspends the process at the proc2 level, where everything is guaranteed
to be copastetic (spelling? A-OK). At least, this is what I have been
told.


 -- David Krowitz

krowitz@richter.mit.edu   (18.83.0.109)
krowitz%richter@eddie.mit.edu
krowitz%richter@athena.mit.edu
krowitz%richter.mit.edu@mitvma.bitnet
(in order of decreasing preference)

rees@MAILGW.CC.UMICH.EDU (Jim Rees) (09/16/88)

        If a process is given a fault_$suspend_proc signal it will stop
    execution until it receives a fault_$continue_proc signal (look
    in /sys/ins/fault.ins.{pas,c,ftn} for their definition). To give
    one of these signals you will have to use /com/sigp with the "-c"
    option. EG: '$ sigp -c 120027 process_151' will cause process_151
    to stop execution.

Another way to do it would be with "kill -STOP".

        The DM 'ds' and 'dc' commands use undocumented system calls to suspend
    and continue a process. These work in the kernal and actually change the
    process manager dispatch status. This will show up in a pst state as 'Susp'.
    This is safer as a 'dc' cannot be blocked by another signal but the process
    must be continued before it will respond to any signal.

You've got this backwards.  "dc" is the more dangerous way.  Since it's a
kernel thing, it ignores user space locking.  If you happen to suspend a
process this way while it's holding some important user space lock (like
the tcp mbuf lock or a DM streams sfcb lock) you can hang the whole node.
-------

Jinfu@cup.portal.com (09/18/88)

I remember there is a pair of DM commands about suepend/resume
process. I think they are DS and DC. However, I never use them
and I always use ppri to lower process prioriety.

JC

GBOPOLY1@NUSVM.BITNET (fclim) (09/21/88)

hi,
      i didn't asked about how to suspend processes.  i believe
someone had misunderstood my queries and had changed the subject.
my questions were about sigp and not crp.  and about shut and
about lock(1) which dave krowitz at mit has informed me has been
implemented by gone on the adus tape.

      i have always use csh and have no problems with suspending
processes.


fclim          --- gbopoly1 % nusvm.bitnet @ cunyvm.cuny.edu
computer centre
singapore polytechnic
dover road
singapore 0513.