Ingres CL PC

From Ingres Community Wiki

Jump to: navigation, search

Ingres Compatability Library
Architecture - Overview - Suggestions - GL: BA - BT - ERGL - handy - HSH - LC - LL - MEGL - MM - MO - MU - PM - SP - TMGL - CL: CI - CK - CM - CP - CS - CSMT - CV - CX - DI - DL - DS - ER - ERold - EX - FP - GC - GV - handy - ID - JF - LG - LK - LO - ME - MH - NM - OL - PC - PE - QU - SA - SI - SR - ST - TC - TE - TH - TM - TR - UT

Contents

Compatibility Library Specification PC

Abstract

This is the specification of the PC facility provided by the compatibility library.

Revision: 1.1, 29-jul-94

Document History

  • Revision 1.1, 29-jul-94
    • The required semantics of the PID type were expanded (23-jul-93).
    • PCforce_exit() and PCis_alive() were added (23-jul-93).
    • PCcmdline no_wait means child lives after parent dies. (5-jun-93, 19-jun-92).
  • Revision 1.0, last modified 29-Aug-91.
    • PCcmdline changed a lot; all old callers need to carefully re-examine their use.
    • Fixed typos.

Specification

Introduction

PC provides facilities for controlling the current process, and for spawning command shells to execute other commands from the current process.

These routines are highly system dependent.

Library

CL

Header File <pc.h>

The header file <pc.h> must be included before using any of the functions provided. It also defines the following.

The PID datatype is a system-specific process ID. Client code should avoid assuming anything about the value of a process ID. The PID datatype needs to be implemented in such a way that it can be passed by value to functions such as PCis_alive and CScp_resume. Furthermore, note that mainline code currently stores PIDs returned from PCpid in shared memory, and later passes those same PID values to PCis_alive() calls in other processes. Thus the PID datatype should be a type that can be passed from process to process and handed back in to these calls in another process (for example, it would be a mistake to make the PID type be the address of a process-private data structure). Normally the operating-system-provided process ID number is used.

typedef ... PID;

Executable Interface

PCatexit - register an exit function

Installs the supplied function as one to be called when PCexit() is called.

Exit functions provide a means of executing code on program exit. They are registered using PCatexit, and called in reverse registration order by PCexit. These functions are called with no arguments, and are not expected to provide any return value.

There is no method of removing a registration, and functions registered multiple times will be called multiple times. Exit functions must be written to do nothing gracefully when called at an inappropriate time. They should be conscious of possible recursion when a function called during the execution of an exit function calls PCexit.

Inputs:

func ptr to a VOID function taking no arguments.

Outputs:

None

Returns:

OK if the registration succeeds, otherwise system specifi error status

Definition:

STATUS PCatexit( func ) 
VOID (*func)();

PCcmdline - execute command line

Invoke default or specified interpreter to execute command line. Null argument for interpreter means use default. If cmdline is NULL, then a shell is invoked. wait is passed with either the values of PC_WAIT or PC_NO_WAIT to determine if PCcmdline should wait for the process to terminated before returning. If a detached process is desired, all errors will be redirected to err_log. A return status other than OK indicates either an error invoking the command or may be the actual status value from the exiting command. A return of OK doesn't mean PCcmdline will map a successful operating system cmopletion status to OK.

Some systems may be unable to create simultaneous processes. On these systems, the value of PC_NO_WAIT will be the same as PC_WAIT, and the function will always wait for termination. Callers may check if PC_WAIT == PC_NO_WAIT to determine if subprocesses are possible. Sub-processes started with PC_NO_WAIT must continue to execute after this invoking program exits. The OS completion status of a PC_NO_WAIT process is not visible in the caller in the status return, nor can the caller know when the called program exits. The only potential channel back from the called process is by examination of the err_log file.

If called with a NULL command line and with PC_NO_WAIT, the behavior is undefined.

If called with a NULL command line, use the specified interpreter, or a default interpreter specified by the user (this is system-dependent), or the system default interpreter, in that order. If called with a command line, use the supplied interpreter or the system default interpreter. For security reasons, user-specified interpreters cannot be used to execute command lines. This is because privileged Ingres programs must ensure that all sub-process commands cannot be subverted by a user's command interpreter.

The only current system on which this becomes an issue is UNIX. Here, the SHELL environment variable is generally used to specify a command interpreter to be executed for a user interactively. Using the first rule above when called to interactively execute a command interpreter (i.e., the default action of a NULL command line is passed), \&'PCcmdline()' would use the command interpreter specified in the SHELL variable, if any.

Inputs:

interpreter a string specifying a non-default command interpreter to use, if there is no command line. If there is a command, the interpreter is ignored.
cmdline A system-specific command to execute. If NULL, a command interpreter is entered.
wait determines if should wait for process to terminate.
err_log location where output and errors are redirected if possible. If PC_WAIT is set may be NULL.
err_code describes the error status.

Outputs:

OK if the command was started successfully, otherwise system specific error status.

Definition:

STATUS
PCcmdline(interpreter, cmdline, wait, err_log, err_code)
LOCATION  *interpreter;
char             *cmdline;
i4              wait;
LOCATION        *err_log;
CL_ERR_DESC     *err_code;

PCcrashself - crash current process

To be used internally to test crash recovery of processes. Implementation of this routine should crash the process in the most severe manner. (ie. on vms stop process without running handlers, on unix "kill -9, ...).

If no other way exists on an OS to exit a program, this routine can always be implemented by a call to PCexit().

Inputs:

None

Outputs:

None

Returns:

Doesn't.

Definition:

VOID
PCcrashself()


PCexit - program exit

Terminate current process. Status is the value returned to shell or command interpreter. PCexit maps the status value to a good operating system status and the calling program exits with that status. OK is mapped to an OS success status. Anything else is mapped to an OS failure status.

All functions registered by PCatexit will be called in the reverse order of their registration. To ensure the validity of the stack when exit functions are called, PCexit may only be called from within main() or its descendants. It may not be called after main() has returned.

Inputs:

status If OK, mapped to system sucess status. If not OK, mapped to some system-specific failure status.

Outputs:

None

Returns:

Doesn't.

Side Effects:

Functions previously registered with PCatexit are called.

Definition:

VOID PCexit(status) 
STATUS status;

PCforce_exit - Cause (another) process to exit

This function can be called to cause the indicated process to exit.

Ingres processes only use this call to force the exit of each other, snot to terminate arbitrary system processes. This means that Ingres installations must be operated in such a way that Ingres processes are permitted to iforce the exit of each other; for example, they may need to be in the same group, or be started by the same user ID, or be marked "setuid" for the same user ID, or some other system specific requirement.

Each environment in which Ingres runs satisfies this using system- specific installation techniques; the PCforce_exit implementation should take into account these considerations so that it can properly cforce the exit of other Ingres processes in the installation.

The target process is not expected to die gracefully. Abrupt termination is acceptable. This call is used only in serious error situations where database integrity requires an immediate and forceful cessation of processing (for example, if the Recovery Process detects that the transaction logfile is experiencing hard I/O errors, it will forcibly shut down all Ingres servers immediately, bringing processing to a halt until the logfile can be repaired).

Graceful termination of the target process (that is, allowing the target process to invoke its PCat_exit functions) is also OK. Thus the caller of this routine cannot make any assumptions about the immediacy or abruptness of the termination of the target process, since the particular implementation on this system may be more or less abrupt.

Inputs:

pid Process to terminate.

Outputs:

err_code Reason for unsuccessful completion.

Returns:

OK Process termination successfully requested.
<other> System-specific problem prevents success.

Definition:

STATUS PCforce_exit( PID pid, CL_ERR_DESC *err_code );

PCis_alive - Is this process still alive?

This function can be called to determine whether a given process is alive or not.

Ingres processes only use this call to inquire on the status of each other, not to check on arbitrary system processes. This means that Ingres installations must be operated in such a way that Ingres processes are permitted to inquire on the status of each other; for example, they may need to be in the same group, or be started by the same user ID, or be marked "setuid" for the same user ID, or some other system specific requirement.

Each environment in which Ingres runs satisfies this using system- specific installation techniques; the PCis_alive implementation should take into account these considerations so that it can properly check on the status of other Ingres processes in the installation.

On many systems, PID's are re-used. If a process dies, and another process is soon thereafter born with the same PID, this function may return TRUE even though the process the caller is interested in is no longer alive. On many systems, PID re-use is particularly common following a system crash. This is unfortunate; however, generic mainline code deals with this using the following techniques:

  • The frequency between calls to this routine is adjustable.
  • This call is used as a "fail-safe" following abnormal process termination
  • Documentation in Ingres system management manuals.
  • Only PIDs which have been generated since the last system crash should be passed to this routine (that is, it is unwise to store a PID in a permanent file, then later pass it to this routine, because the system might well have crashed and been rebooted since the PID was generated).

Inputs:

pid Process to check

Outputs:

none

Returns:

TRUE Process appears to be alive. We also return TRUE if we can't tell whether the process is alive because a system problem keeps us from finding out.
FALSE Process is definitely NOT alive

Definition:

bool PCis_alive( PID pid );

PCpid - get current process id

Assign to pid the current process id.

Inputs:

None

Outputs:

pid pointer to a PID filled in with the right value for the current process.

Definition:

VOID
PCpid(pid)
PID      *pid;

PCsleep - process sleep

Sleep for msec milliseconds. Resolution only guaranteed to seconds.

Inputs:

msec nominal milliseconds to sleep.

Outputs:

None

Returns:

None

Definition:

VOID
PCsleep(msec)
u_i4        msec;

PCunique - return a unique string

Fills in the buffer pointed to by uniquestr with a null terminated string that uniquely identifies the process. If MAXFILENAME is the maximum length of the name part of a file, then the length of the returned string is at most MAXFILENAME - 4.

Inputs:

None

Outputs:

uniquestr pointer to a buffer that is at least MAXFILENAME in length, filled in with a string unique to the process.

Returns:

None

Definition:

VOID
PCunique(uniquestr)
char uniquestr[MAXFILENAME + 1];

Examples

The following shows how to use and implement the PCatexit/PCexit calls. A program which ensures the terminal is left in a sane state, even if a called function calls PCexit() at a graceless time.

# include <compat.h>
# include <pc.h>
# include <te.h>
VOID
cleanup()
{
       _VOID_ TErestore( TE_NORMAL );
}
main()
{
       _VOID_ PCatexit( cleanup );
       _VOID_ TErestore( TE_FORMS );
       bunch_o_stuff();
       PCexit( OK );
       /* NOTREACHED */
}

bunch_o_stuff()
{
       ...
       if( bad_phase_of_the_moon )
       {
              PCexit( FAIL );
              /* NOTREACHED */
       }
}

A program showing how to trap exits using EX. C setjmp and longjmp would work just as well and be more approriate in a user application.

# include <ex.h>
VOID
oops()
{
   EXsignal( YOUR_EXCEPTION, 0 );
}
STATUS
handler( args )
EX_ARGS *args;
{
   return( args->exarg_num == YOUR_EXCEPTION ? EXDECLARE : EXRESIGNAL );
}
/* ARGSUSED */
    main(argc, argv)
    int argc;
    char **argv;
{
    bunch_of_startup_code();
    doit();
    return( OK );
}
doit()
{
   EX_CONTEXT context;
   PCatexit( oops );
   EXdeclare( handler, &context );
   open_network_connection();
   do_net_work()
   close_network();
   EXdelete();
}
do_net_work()
{
   while( getcmd() != EXIT )
   {
       if( sendcmd() == NET_DOWN )
           PCexit( 1 );
       if( getanswer() = NET_DOWN )
           PCexit( 1 );
       writeanswer();
   }
}

UNIX IMPLEMENTATION

This is a crib for versions that may be needed on other systems.

# include <compat.h>
# define MAXFUNCS      32

static VOID (*Exitfuncs[ MAXFUNCS ])();
static VOID (**Lastfunc)() = Exitfuncs;

VOID
PCexit(status)
i4 status;
{
       register VOID (**f)() = Lastfunc;

       while( f-- != Exitfuncs )
              (**f)();

       (void)exit( (int)status );
       /*NOTREACHED*/
}
STATUS
PCatexit( func )
VOID (*func)();
{
       if( Lastfunc >= &Exitfuncs[ MAXFUNCS ] )
              return( FAIL );
       *Lastfunc++ = func;
       return( OK );
}


Ingres Compatability Library
Architecture - Overview - Suggestions - GL: BA - BT - ERGL - handy - HSH - LC - LL - MEGL - MM - MO - MU - PM - SP - TMGL - CL: CI - CK - CM - CP - CS - CSMT - CV - CX - DI - DL - DS - ER - ERold - EX - FP - GC - GV - handy - ID - JF - LG - LK - LO - ME - MH - NM - OL - PC - PE - QU - SA - SI - SR - ST - TC - TE - TH - TM - TR - UT

Personal tools
Developing With