Saving data on signals

Quantify installs signal handlers for many of the software signals that can be delivered to a Quantify'd process. The signal handler saves performance data to a file before proceeding with the normal signal behavior (which typically involves termination of the program). If you have already installed a signal handler for a given signal, Quantify does not save data when it receives that signal.

The initial default set of signals handled by Quantify are:

SIGHUP, SIGINT, SIGIOT, SIGQUIT, SIGILL, SIGABRT, SIGEMT, SIGFPE, SIGBUS, SIGSEGV, SIGSYS, SIGPIPE, SIGTERM, SIGUSR1, SIGURSR2, SIGLOST, SIGXCPU, SIGXFSZ,

SIGHUP, SIGINT, SIGIOT, SIGQUIT, SIGILL, SIGABRT, SIGEMT, SIGFPE, SIGBUS, SIGSEGV, SIGSYS, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2, SIGPOLL, SIGRTMIN, SIGRTMAX, SIGXFSZ, SIGXCPU, SIGXFSZ,

SIGHUP, SIGINT, SIGIOT, SIGQUIT, SIGILL, SIGABRT, SIGEMT, SIGFPE, SIGBUS, SIGSEGV, SIGSYS, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2, SIGLOST, SIGRESERVE, SIGDIL, SIGXCPU, SIGXFSZ

To ignore signals in this list, use the -ignore-signals option. Specify a comma-separated list of signals to ignore. For example:

% setenv QUANTIFYOPTIONS -ignore-signals=SIGSEGV,SIGBUS

To handle additional signals, use the -handle-signals option. Specify a comma-separated list of additional signals. For example:

% setenv QUANTIFYOPTIONS -handle-signals=SIGALARM,SIGCHLD

Quantify does not handle SIGKILL, SIGTSTOP, and SIGTRAP, since doing so interferes with normal program operation. If you specify these signals with -handle-signals, Quantify silently ignores them.

If you do not want Quantify to save data on any signals, specify:

% setenv QUANTIFYOPTIONS -save-data-on-signals=no

Collecting data in long-running programs

If you have a program, such as a daemon, that does not exit, you can capture Quantify data and save it to a file while the program is running, without terminating the program. You can use either of these methods:

Write a signal handler for a given signal that calls the Quantify API function quantify_save_data. To clear the Quantify counters, call quantify_clear_data.

Use the -api-handler-signals option to install signal handlers. For example, -api-handler-signals=SIGUSR1,SIGUSR2 installs signal handlers for the SIGUSR1 and SIGUSR2 signals. When the program receives the first signal (SIGUSR1), quantify_save_data is called. When the program receives the second signal (SIGUSR2), quantify_clear_data is called.

To send the signal to the process, type:

% kill -USR1 <pid>

This causes Quantify to write the data to the next dataset number. You can view that data with qv immediately after the file is written, while the daemon continues to run. Quantify automatically resets its counters to zero after saving the data, ensuring that the next incremental dataset will contain the data since the last save.

For additional information on signals, see the signal, sigvec, and sigmask manual pages, and the /usr/include/signal.h and /usr/include/sys/signal.h files.

Collecting data for child processes

Programs often create child processes using fork or vfork. When these child processes start, they execute from the current data state of the parent, typically to perform some computation based on data the parent provides. For example, the parent process might fork a child process to handle a request from the client to update a data record. Child processes, rather than the parent processes, are often the actual site of the performance bottlenecks in a program. To capture the performance data from these separate processes, Quantify must start a different instance of itself for each child process before the child process executes.

Using execve

Sometimes child processes immediately call execve to start running a different program altogether. In this case, the effort of starting a new copy of Quantify for the child process is wasted. Therefore, by default, Quantify does not start Quantify to record child process data. To record child process data, set the -record-child-process-data option:

% setenv QUANTIFYOPTIONS -record-child-process-data=yes

By default, Quantify saves data for each child process in a different file, since the filename prefix includes the %p character, which expands to the process ID of each child.

Using fork

Since the operating system makes a copy of the memory state during a fork, the counts for the child process include the counts from the parent process up to the point of the fork. To exclude the parent data from the child process data, you can call the quantify_clear_data API function after the child process begins.

Using vfork

The vfork system call creates a child process that shares the same memory image as its parent process. The parent process is suspended until the child exits. Since Quantify keeps its counter data in memory, as the child process executes it adds the counts to the parent's counters, thereby corrupting the parent's data. To prevent this, Quantify intercepts all vfork calls and converts them to fork calls. The fork system call ensures that the child is an independent process with its own memory state. Since the child is Quantify'd, its data is reported under a separate process ID, if -record-child-process-data=yes.