Dynamic Probe Class Library

Dynamic Probe Class Library Programming Guide


Chapter 7. Controlling execution of target application processes

There are two relationships that an analysis tool can establish with a target application process in order to affect its execution. The analysis tool can "connect" to the process, and, once connected, can also "attach" itself to the process. Connection (described in detail in Chapter 6, Connecting to or starting the target application processes) establishes a communication channel to the host where the process resides and creates the environment within the process that allows the analysis tool to insert and remove instrumentation probes. Inserting instrumentation probes enables the analysis tool to indirectly influence the execution of a target application process.

An analysis tool can connect to processes either by explicitly connecting (by calling the connect or bconnect function of either the Process or Application class), or by creating them (by calling the create or bcreate function of either the Process or PoeAppl class). The connect and bconnect functions place the process(es) in a connected state represented by the enumeration constant PRC_connected of the Process class' ConnectState enumeration type. The create and bcreate functions place the process(es) in a created state represented by the enumeration constant PRC_created of the Process class' ConnectState enumeration type. A subsequent call to the start or bstart function will move the process(es) into the PRC_connected state. In either case, however, a connection has been established that enables the analysis tool to instrument the target application process(es) with probes.

When a process is connected (in either the PRC_connected or PRC_created state), the analysis tool can attach to the process using the attach or battach function of either the Process or Application class. Attaching to the process enables the analysis tool to control execution of the process directly. This direct process control is exclusive -- no other analysis tool will be able to attach to the process. The following sections describe how an analysis tool can:

The analysis tool can also terminate a process. If the process is in the PRC_created state, the analysis tool does not need to attach to it in order to terminate its execution. If the analysis tool has, on the other hand, not created but merely connected to a remote process, it must attach to the process in order to terminate it. The analysis terminates one or more processes by calling the Process::destroy, Process::bdestroy, Application::destroy, or Application::bdestroy function.


Attaching to the target application process(es)

Attaching to a target application process enables an analysis tool to directly control the execution of the process. This includes resuming and suspending execution of the process (as described in Resuming execution of the target application process(es) and Suspending execution of the target application process(es)), as well as terminating the process (as described in Terminating target application processes). Attaching to an application automatically suspends its execution. This enables the analysis tool to install probes in the process (as described in Chapter 9, Executing probes in target application processes) before resuming its execution (as described in Resuming execution of the target application process(es)).

In order to attach itself to one or more target application processes, the analysis tool must be connected to the process(es) as described in Connecting to the target application. In other words, the Process object must be in either the PRC_connected or PRC_created state; the analysis tool can query a Process object's state by calling the Process::query_state function.

To attach to a single process, the analysis tool can use the asynchronous function Process::attach or its blocking equivalent Process::battach. To attach to processes on an application-wide basis (for all Process objects managed by an Application object), the analysis tool can use the functions Application::attach or Application::battach.

Table 31. Attaching to one or more target application processes
To attach: To a single process (Process object) To multiple processes (all of the Process objects managed by an Application object)
Using the asynchronous function attach
AisStatus sts = p->attach(attach_cb, 

          (GCBTagType) 0);

    check_status("p->attach(attach_cb, 

          (GCBTagType) 0)", sts);

 

 

//

// callback to be called after the attach 

// completes

//

void attach_cb(GCBSysType sys, 

          GCBTagType tag, GCBObjType obj, 

          GCBMsgType msg)

{

 

      // code within callback routine

      // can check the status of the

      // operation and respond to its

      // completion by, for example,

      // continuing with other work 

 

}


AisStatus sts = a->attach(attach_cb, tag);

        check_status("a->attach(attac_cbh, 

            tag)", sts);

 

 

//

// callback to be called after the attach 

// completes for each Process managed by

// this Application object

//

void attach_cb(GCBSysType sys, 

          GCBTagType tag, GCBObjType obj, 

          GCBMsgType msg)

{

 

      // code within callback routine

      // can check the status of the

      // operation and respond to its

      // completion by, for example,

      // continuing with other work 

 

}


Using the blocking function battach
sts = P.battach();

    check_status("P.battach()", sts);

    printf("  %s: attached to pid:%d\n", 

            toolname,  P.get_pid());


sts = A.battach();

    check_status("A.battach()", sts);

    printf("  %s: attached to A\n", 

          toolname);


Attaching to a process puts the process in an attached state represented by the enumeration constant PRC_attached of the Process class' ConnectState enumeration type. The analysis tool can query a Process object's state by calling the Process::query_state function.

Once attached to one or more target application processes, the analysis tool can:

Note that only one analysis tool can be attached to a particular process at a time. For this reason, an analysis tool may want to "detach" itself from a particular process when it no longer needs to directly control its execution. To do this, see Detaching from target application processes.

For more information on the Process::attach, Process::battach, Application::attach, and Application::battach functions, refer to their UNIX man pages or their entries in the DPCL Class Reference.


Resuming execution of the target application process(es)

When the analysis tool attaches to one or more target application processes (as described in Attaching to the target application process(es)), execution of the process(es) is temporarily suspended. By suspending a process when the analysis tool attaches to it, the DPCL system enables the analysis tool to perform actions on it before resuming its execution. If the analysis tool were a debugger, for example, this would enable it to examine the processes state. Also, an analysis tool could install probes into the target application (as described in Chapter 9, Executing probes in target application processes) before resuming its execution. Once the analysis tool has resumed execution of a process, it can explicitly suspend its execution again as described in Suspending execution of the target application process(es).

To resume execution of a single suspended process, the analysis tool can use the asynchronous function Process::resume or its blocking equivalent Process::bresume. To resume execution of suspended processes on an application-wide basis (for all Process objects managed by an Application object), the analysis tool can use the Application::resume or Application::bresume functions.

Table 32. Resuming execution of one or more suspended target application processes
To resume execution: Of a single process (Process object) Of multiple processes (all of the Process objects managed by an Application object)
Using the asynchronous function resume
AisStatus sts = p->resume(resume_cb, 

          GCBTagType(0));

    check_status("p->resume(resume_cb, 

          GCBTagType(0))", sts);

 

 

//

// callback to be called after the resume 

// completes

//

void resume_cb(GCBSysType sys, 

          GCBTagType tag, GCBObjType obj, 

          GCBMsgType msg)

{

 

      // code within callback routine

      // can check the status of the

      // operation and respond to its

      // completion by, for example,

      // continuing with other work 

 

}


AisStatus sts = A.resume( resume_cb, 

        GCBTagType(0) );

if ( sts.status() != ASC_success ) {

	printf("A.resume(), status: %s\n", 

        sts.status_name());

	return sts;

}

 

 

//

// this is called after each process 

// resume request has completed

//

void resume_cb(GCBSysType sys, GCBTagType tag, 

        GCBObjType obj, GCBMsgType msg)

{

	AisStatus *stsp = (AisStatus *)msg;

	if ( stsp->status() != ASC_success )

		printf("resume_cb, status: %s\n", 

        stsp->status_name());

}


Using the blocking function bresume
sts = P.bresume();

    check_status("P.bresume()", sts);

    printf("  %s: resumed pid:%d\n", 

            toolname,  P.get_pid());


AisStatus sts=A.bresume();

return sts;


Note that the process must be attached in order for the analysis tool to resume its execution. In other words, the Process object must be in the PRC_attached state; the analysis tool can query a Process object's state by calling the Process::query_state function.

For more information on the Process::resume, Process::bresume, Application::resume, or Application::bresume functions, refer to their UNIX man pages, or their entries in the DPCL Class Reference


Suspending execution of the target application process(es)

When the analysis tool attaches to one or more target application processes (as described in Attaching to the target application process(es)), the DPCL system automatically suspends execution of the process(es). This enables the analysis tool to install probes in the process(es) (as described in Chapter 9, Executing probes in target application processes). When desired, the analysis tool then resumes execution of the processes as described in Resuming execution of the target application process(es). After execution of a process has been resumed, the analysis tool can suspend it again.

To suspend execution of a single process, the analysis tool can use the asynchronous function Process::suspend or its blocking equivalent Process::bsuspend. To suspend execution of processes on an application-wide basis (for all Process objects managed by an Application object), the analysis tool can use the Application::suspend or Application::bsuspend functions.

Table 33. Suspending execution of one or more target application processes
To suspend execution of: A single process (Process object) Multiple processes (all of the Process objects managed by an Application object)
Using the asynchronous function suspend
AisStatus sts = p->suspend(suspend_cb, 

          GCBTagType(0));

    check_status("p->suspend(suspend_cb, 

          GCBTagType(0))", sts);

 

 

//

// callback to be called after the suspend 

// completes

//

void suspend_cb(GCBSysType sys, 

        GCBTagType tag, GCBObjType obj, 

        GCBMsgType msg)

{

 

      // code within callback routine

      // can check the status of the

      // operation and respond to its

      // completion by, for example,

      // continuing with other work 

 

}


AisStatus sts = A.suspend( suspend_cb, 

        GCBTagType(0) );

	if ( sts.status() != ASC_success )

		return sts;

 

 

//

// this is called after each process's 

// suspend request is done

//

void suspend_cb(GCBSysType sys, GCBTagType tag, 

        GCBObjType obj, GCBMsgType msg)

{

	Process *pp = (Process *)obj;

	printf("pid %d suspended\n", pp->get_pid());

}


Using the blocking function bsuspend
sts = P.bsuspend();

    check_status("P.bsuspend()", sts);

    printf("  %s: suspended pid:%d\n", 

            toolname,  P.get_pid());


AisStatus sts=A.bsuspend();

 

//  if app status bad, show status by process 

if ( sts.status() != ASC_success )

	for (int i; i<A.get_count; i++)

		printf("status for Process[%d]: %s\n", 

        i, status(i).status_name);

 


Note that the process must be attached in order for the analysis tool to suspend its execution. In other words, the Process object must be in the PRC_attached state; the analysis tool can query a Process object's state by calling the Process::query_state function.

For more information on the Process::suspend, Process::bsuspend, Application::suspend, and Application::bsuspend functions, refer to their UNIX man pages or their entries in the DPCL Class Reference


Terminating target application processes

When attached to a target application process (in other words, when the Process is in the PRC_attached state), the analysis tool can terminate execution of the process. The analysis tool can also terminate a process if it has created the process (in other words, when the Process is in the PRC_created state). If it has created the process, the analysis tool does not need to attach to it in order to terminate its execution. If the analysis tool has, on the other hand, merely connected to a running process, it must attach to the process in order to terminate it. To determine if a process is in one of the required states (PRC_created or PRC_attached), the analysis tool can query its state by calling the Process::query_state function. To terminate a single target application process, the analysis tool can use the asynchronous function Process::destroy or its blocking equivalent Process::bdestroy. To terminate processes on an application-wide basis (for all Process objects managed by an Application object), the analysis tool can use the functions Application::destroy or Application::bdestroy. When using any of these functions, however, the analysis tool should exercise the same caution it would use when calling the UNIX command kill. Killing selected processes in a message-passing parallel program, for example, could result in program deadlock among the remaining processes.

Table 34. Terminating one or more target application processes
To terminate: A single process (Process object) Multiple processes (all of the Process objects managed by an Application object)
Using the asynchronous function destroy
AisStatus sts = p->destroy(destroy_cb, 

          GCBTagType(0));

    check_status("p->destroy(destroy_cb, 

          GCBTagType(0))", sts);

 

 

//

// callback to be called after the 

// destroy completes

//

void destroy_cb(GCBSysType sys, 

          GCBTagType tag, GCBObjType obj, 

          GCBMsgType msg)

{

 

      // code within callback routine

      // can check the status of the

      // operation and respond to its

      // completion by, for example,

      // continuing with other work 

 

}


AisStatus sts = a->destroy(destroy_cb, tag);

  check_status("a->destroy(destroy_cb, 

                tag)", sts);

 

 

//

// callback to be called after the destroy 

// completes for each Process managed by

// the Application object

//

void destroy_cb(GCBSysType sys, 

          GCBTagType tag, GCBObjType obj, 

          GCBMsgType msg)

{

 

      // code within callback routine

      // can check the status of the

      // operation and respond to its

      // completion by, for example,

      // continuing with other work 

 

}


Using the blocking function bdestroy
sts = P.bdestroy();

    check_status("P.bdestroy()", sts);

    printf("  %s: destroyed pid:%d\n", 

            toolname,  P.get_pid());


sts = A.bdestroy();

   check_status("A.bdestroy()", sts);

   printf("  %s: destroyed Application A\n", 

           toolname);


Destroying a one or more processes as shown in the preceding table places the Process object(s) in a destroyed state. This state is represented by the enumeration constant PRC_destroyed of the Process class' ConnectState enumeration type. The analysis tool can query a Process object's state by calling the Process::query_state function.

For more information on the Process::destroy, Process::bdestroy, Application::destroy, or Application::bdestroy functions, refer to their UNIX man pages or their entries in the DPCL Class Reference.


Detaching from target application processes

An analysis tool does not need to explicitly detach itself from the target application process. When either the analysis tool process or the target application process terminates, the attachment will, or course, be broken. However, it is also important to note that only one analysis tool can be attached to a particular process at a time. For this reason, an analysis tool may want to detach itself from the process when it no longer needs to control execution of the process. This enables another analysis tool to attach to the process.

To detach itself from a single process, the analysis tool can use the asynchronous function Process::detach or its blocking equivalent Process::bdetach. To detach itself from processes on an application-wide basis (for all Process objects managed by an Application object), the analysis tool can use the functions Application::detach or Application::bdetach. Naturally the process must be attached in order for the analysis tool to detach it. In other words, the Process object must be in the PRC_attached state; the analysis tool can query a Process object's state by calling the Process::query_state function.

Table 35. Detaching from one or more target application processes
To detach: From a single process (Process object) From multiple processes (all of the Process objects managed by an Application object)
Using the asynchronous function detach
AisStatus sts = p->detach(detach_cb, 

          GCBTagType(0));

    check_status("p->detach(detach_cb, 

          GCBTagType(0))", sts);

 

 

//

// callback to be called after the

// detach completes

//

void detach_cb(GCBSysType sys, 

          GCBTagType tag, GCBObjType obj, 

          GCBMsgType msg)

 

      // code within callback routine

      // can check the status of the

      // operation and respond to its

      // completion by, for example,

      // continuing with other work 

 

}


AisStatus sts = A.detach( detach_cb, 

        GCBTagType(0) );

if ( sts.status() != ASC_success )

	return sts.status_name();

 

 

//

// this is called after each detach request is 

// complete

//

void detach_cb(GCBSysType sys, GCBTagType tag, 

        GCBObjType obj, GCBMsgType msg)

{

	AisStatus *stsp = (AisStatus *) msg;

	Process *pp = (Process *)obj;

	if (stsp->status() == ASC_success)

		printf("pid %d detached\n", 

              pp->get_pid());

	else

		printf("pid %d not detached\n", 

              pp->get_pid());

}


Using the blocking function bdetach
sts = P.bdetach();

    check_status("P.bdetach()", sts);

    printf("  %s: detached from pid:%d\n", 

            toolname,  P.get_pid());


AisStatus sts=A.bdetach();

 

if ( sts.status() != ASC_success )

	return sts;


For more information on the Process::detach, Process::bdetach, Application::detach, and Application::bdetach functions, refer to their UNIX man pages or their entries in the DPCL Class Reference

Note that detaching from a target application process does not remove the analysis tool's connection to the process. The analysis tool will still be able to install and execute probes within the process.


Example: Controlling execution of target application processes

The following example illustrates how a target application can control execution of target application processes. Specifically, it illustrates the use of the Application::bsuspend, Application::bresume, Application::bdetach, and Application::bdestroy calls. The user passes this analysis tool the host name and process IDs of the target application processes. The analysis tool:

  1. connects and attaches to the processes. Attaching to the processes suspends their execution.
  2. calls a program function to insert point probes into the processes. (See Chapter 9, Executing probes in target application processes for more information on inserting point probes.)
  3. resumes execution of the processes.

    Once execution of the processes resumes, the installed point probes collect information until the user presses a key on the keyboard. The target application then:

  4. suspends execution of the target application processes,
  5. removes the point probes, and
  6. if the program was compiled with the flag -DLET_RUN, detaches and disconnects from the target application processes. If the program was not compiled with -DLET_RUN, the analysis tool terminates the target application processes.
//

// Example DPCL program for bsuspend, bresume, bdetach

// and bdestroy calls.

// Compile with -DLET_RUN if you want the application to

// continue running after instrumenting it.

//

 

#include <stdlib.h>

#include <stdio.h>

#include <dpcl.h>

 

AisStatus instrument(Application A);

void insert_probes();

void remove_probes();

void wait_for_keystroke();

 

main(int argc, char *argv[])

{

	Application A;

	char hostname[128];	

	int pid_list[128]; 

	int pid_count;

 

	if (argc <3) {

		printf("Usage: %s <hostname> <pid> [pid...]\n", argv[0]);

		exit(-1);

	}

 

	// get the hostname and pids from argv

	//

	strcpy(hostname, argv[1]);

	pid_count=argc-2;

	for (int i=0; i<pid_count; i++) {

		pid_list[i] = atoi(argv[i+2]);

	}

 

	Ais_initialize();

 

	// Call the Process constructor then

	// add the processes to the application

	//

	for (i=0; i<pid_count; i++) {

		Process p(hostname, pid_list[i]);

		A.add_process(&p);

	}

 

	// call this routine to instrument the application

	//

	AisStatus sts = instrument(A);

 

	// very basic error checking

	//

	if ( sts.status() != ASC_success ) {

 

		// print overall status for application

		//

		printf("Failed with overall status: %s\n", sts.status_name());

 

		// print individual status for processes in application

		//

		for (int i=0; i<A.get_count(); i++)

			printf("status for Process[%d]: %s\n", i, A.status(i).status_name());

		exit(-1);

	}

}

 

AisStatus instrument(Application A)

{

	//  connect to the application

	//

	AisStatus sts=A.bconnect();

	if ( sts.status() != ASC_success ) return sts;

 

	//  attach to the application

	//

	sts=A.battach();

	if ( sts.status() != ASC_success ) return sts;

 

	//	Instrument the application

	//

	insert_probes();

 

	//  resume the application

	//

	sts=A.bresume();

	if ( sts.status() != ASC_success ) return sts;

 

	//	collect instrumentation until there is user input

	//

	wait_for_keystroke();

 

	//  suspend the application

	//

	sts=A.bsuspend();

	if ( sts.status() != ASC_success ) return sts;

 

	//	remove the instrumentation

	//

	remove_probes();

 

	//  resume the application

	//

	sts=A.bresume();

	if ( sts.status() != ASC_success ) return sts;

 

#ifdef LET_RUN

 

	//  detach from the application

	//

	sts=A.bdetach();

	if ( sts.status() != ASC_success ) return sts;

 

	//  let the application go on normally

	//

	sts=A.bdisconnect();

	if ( sts.status() != ASC_success ) return sts;

 

#else

 

	//  let the application go on normally

	//

	sts=A.bdestroy();

	if ( sts.status() != ASC_success ) return sts;

 

#endif // LET_RUN

 

	return sts;

}

 

// dummy function defs

void insert_probes() {}

void remove_probes() {}

void wait_for_keystroke() {}


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]