Qp0zDumpTargetStack()--Dump Formatted Stack Trace Data of the Target Thread


  Syntax
 #include <qp0ztrc.h>

 int Qp0zDumpTargetStack(int handle,
                         const char *label);

  Service Program Name: QP0ZCPA

  Default Public Authority: *USE

  Threadsafe: Conditional; see Usage Notes.

The Qp0zDumpTargetStack() function dumps a formatted representation of the call stack of the target thread to the user trace. The target thread is specified by handle, which can be filled in using the pthread_t structure. The formatted call stack is labeled with the text string specified by label. The formatted call stack shows the library, program, module, and procedure information associated with each frame on the call stack at the time the function was called.

The formatted dump of the target call stack shows the oldest entries first, followed by newer entries.

For consistent results, ensure that the target thread specified in the handle parameter is blocked or waiting for some resource and not actively running.

If a target thread that is actively running is specified, the stack trace information may be inconsistent.

An application should not use the tracing function in performance critical code. These functions are intended for debugging exception or error conditions. The user trace is a permanent user space object named QP0Z<jobnumber> in the QUSRSYS library. The user trace is created the first time any thread in a job writes trace output. See the Change User Trace (CHGUSRTRC), Dump User Trace (DMPUSRTRC) and Delete User Trace (DLTUSRTRC) CL commands for information about manipulating the user trace properties and objects.


Parameters

handle
(Input) A handle to the target thread.

label
(Input) A pointer to a string that is used to label the stack dump.

Authorities

None.


Return Value

0 Qp0zDumpTargetStack() was successful.
value Qp0zDumpTargetStack() was not successful. The value returned is an errno indicating the failure.


Error Conditions

If Qp0zDumpTargetStack() is not successful, the return value usually indicates one of the following errors. Under some conditions, the return value could indicate an error other than those listed here.

[EFAULT]

The address used for an argument is not correct.

In attempting to use an argument in a call, the system detected an address that is not valid.

While attempting to access a parameter passed to this function, the system detected an address that is not valid.

[ESRCH]

No item could be found that matches the specified value.



Usage Notes

  1. No locks are held on the user trace between calls to the tracing functions. The user trace can be deleted while in use. The next function that produces trace output will create the user trace again.

  2. If another job on the system has the same job number as an existing user trace, the existing trace data is cleared, and the trace data from the new job replaces it.

  3. The Qp0zDumpTargetStack() can only safely be used against a thread that is stopped or waiting for some activity to occur. If Qp0zDumpTargetStack() is used with a thread that is actively running, the output stack trace may show an inconsistent view of the call stack.

  4. If the target thread has more than 128 call stack entries, Qp0zDumpTargetStack() returns after dumping the first 128 entries of the call stack.

  5. As the format of the user trace records can change, only the following CL commands can be used to manipulate the user trace properties and objects:

Related Information


Example

The following example uses Qp0zDumpTargetStack() and Qp0zUprintf() functions to produce trace output.

Note: By using the code examples, you agree to the terms of the Code license and disclaimer information.

#define _MULTI_THREADED
#include <pthread.h>
#include <milib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <qp0ztrc.h>

void *threadfunc(void *);

int main(int argc, char **argv)
{
  int                   rc=0;
  pthread_t             thread;

  Qp0zUprintf("Entering Testcase\n");
  rc = pthread_create(&thread, NULL, threadfunc, NULL);
  sleep(2);  /* Let the thread block */

  /* If the other thread ends or is actively running (that is       */
  /* changing the call stack, you may get meaningless results in the*/
  /* stack dump for the target thread.)                             */
  Qp0zDumpTargetStack(thread.reservedHandle,
                      "Dumping target thread's stack\n");
  Qp0zUprintf("Exit with return code of 0\n");
  return 0;
}


void foo(void);
void bar(void);
void *threadfunc(void *parm)
{
  Qp0zUprintf("Inside secondary thread\n");
  foo();
  return NULL;
}

void foo(void)
{
  bar();
}

void bar(void)
{
  Qp0zDumpStack("Thread dumping my own stack\n");
  sleep(10); /* Ensure the thread is blocked */
}


Trace Output:

This trace output was generated after the test case was run by using the CL command DMPUSRTRC JOB(107141/USER/TPZTSTK0) OUTPUT(*STDOUT). The above example program ran as job 107141/USER/TPZTSTK0.

Note the following in the trace output:

  1. Each trace record is indented by several spaces to aid in readability. Trace records from different threads have different indentation levels.

  2. Each trace record is identified by the hexadecimal thread ID, a colon, and a timestamp. The timestamp can be used to aid in debugging of waiting or looping threads. For example, the third trace record shown below, (the Entering Testcase trace point) was created by thread 0x36, and occurred 0.595584 seconds after the last full date and time label. This means that the trace record was created on 23 January 1998 at 12:38:10.595584. A full date and time label is placed between those trace points that occur during different whole seconds.


User Trace Dump for job 107141/USER/TPZTSTK0. Size: 300K, Wrapped 0 times.
--- 01/23/1998 12:38:10 ---
  00000036:595584 Entering Testcase
  00000037:598832 Inside secondary thread
  00000037:599024 Stack Dump For Current Thread
  00000037:599200 Stack:  Thread dumping my own stack
  00000037:695440 Stack:  Library    / Program     Module      Stmt    Procedure
  00000037:752984 Stack:  QSYS       / QLESPI      QLECRTTH    774   : LE_Create_Thread2__FP12crtth_parm_t
  00000037:805664 Stack:  QSYS       / QP0WPTHR    QP0WPTHR    1006  : pthread_create_part2
  00000037:805888 Stack:  QP0WTEST   / TPZTSTK0    TPZTSTK0    2     : threadfunc
  00000037:806088 Stack:  QP0WTEST   / TPZTSTK0    TPZTSTK0    1     : foo
  00000037:806288 Stack:  QP0WTEST   / TPZTSTK0    TPZTSTK0    1     : bar
  00000037:806496 Stack:  QSYS       / QP0ZCPA     QP0ZUDBG    85    : Qp0zDumpStack
  00000037:848280 Stack:  QSYS       / QP0ZSCPA    QP0ZSCPA    274   : Qp0zSUDumpStack
  00000037:848504 Stack:  QSYS       / QP0ZSCPA    QP0ZSCPA    285   : Qp0zSUDumpTargetStack
  00000037:848616 Stack:  Completed
 --- 01/23/1998 12:38:12 ---
  00000036:628272 Stack Dump For Target Thread: Handle 7 (0x00000007)
  00000036:628464 Stack:  Dumping target thread's stack
  00000036:651608 Stack:  Library    / Program     Module      Stmt    Procedure
  00000036:651872 Stack:  QSYS       / QLESPI      QLECRTTH    774   : LE_Create_Thread2__FP12crtth_parm_t
  00000036:652088 Stack:  QSYS       / QP0WPTHR    QP0WPTHR    1006  : pthread_create_part2
  00000036:652304 Stack:  QP0WTEST   / TPZTSTK0    TPZTSTK0    2     : threadfunc
  00000036:652512 Stack:  QP0WTEST   / TPZTSTK0    TPZTSTK0    1     : foo
  00000036:652712 Stack:  QP0WTEST   / TPZTSTK0    TPZTSTK0    2     : bar
  00000036:677456 Stack:  QSYS       / QP0SSRV1    QP0SLIB     1061  : sleep
  00000036:700096 Stack:  QSYS       / QP0SSRV2    QP0SWAIT    248   : qp0swait__FP13qp0ssigwait_t
  00000036:700216 Stack:  Completed
  00000036:700408 Exit with return code of 0
Press ENTER to end terminal session.


API introduced: V4R3

[ Back to top | Problem Management APIs | APIs by category ]