1 /*
2    (C) 2007 by Argonne National Laboratory.
3        See COPYRIGHT in top-level directory.
4 */
5 #include "mpe_callstack_conf.h"
6 
7 #if defined( STDC_HEADERS ) || defined( HAVE_STDIO_H )
8 #include <stdio.h>
9 #endif
10 #if defined( STDC_HEADERS ) || defined( HAVE_STRING_H )
11 #include <string.h>
12 #endif
13 #if defined( HAVE_UNISTD_H )
14 #include <unistd.h>
15 #endif
16 #if defined( HAVE_FCNTL_H )
17 #include <fcntl.h>
18 #endif
19 
20 #include "mpe_callstack.h"
21 
22 #if defined( NEEDS_FDOPEN_DECL )
23 extern FILE* fdopen( int, const char * );
24 #endif
25 
26 /*@
27     MPE_CallStack_iteratorInit() -- Initialize the iterator for the
28                                     back trace of the CallStack.
29 
30     Input Parameters:
31 .   cstk   - Pointer to MPE_CallStack_t.
32 @*/
MPE_CallStack_iteratorInit(MPE_CallStack_t * cstk)33 void MPE_CallStack_iteratorInit( MPE_CallStack_t *cstk )
34 {
35     int    pipefds[2];
36     /* Connect a pipe to the fd used in backtrace_symbols_fd(). */
37 #ifdef HAVE_WINDOWS_H
38     /*FIXME: CreatePipe() --- windows */
39 #else
40     int    ierr;
41     ierr = pipe( pipefds );
42 #endif
43     /* Set the writing end of the pipe non-blocking */
44 #ifdef HAVE_WINDOWS_H
45     /*FIXME: Set write fd non-blocking */
46 #else
47     fcntl( pipefds[1], F_SETFL, O_NONBLOCK );
48 #endif
49     MPE_CallStack_print( cstk, pipefds[1] );
50     /* Close the pipe so EOF is sent to the reading end of the pipe */
51     close( pipefds[1] );
52     cstk->pipefile = fdopen( pipefds[0], "r" );
53     memset( cstk->line_buf, 0, MPE_CALLSTACK_MAXLINE );
54 #if defined( HAVE_PRINTSTACK )
55     /* Take off the stackframe that contains this function call. */
56     MPE_CallStack_iteratorHasMore( cstk );
57 #endif
58 }
59 
60 /*@
61     MPE_CallStack_iteratorHasMore - Check if the iterator contains any
62                                     more of CallStack frame.
63 
64     Input Parameters:
65 .   cstk   - Pointer to MPE_CallStack_t.
66 
67     Returns:
68        true, 1, if a complete record (i.e. with '\n' ) of callstack is found
69       false, 0, if the end of stack output is reached or error in reading.
70 @*/
MPE_CallStack_iteratorHasMore(MPE_CallStack_t * cstk)71 int MPE_CallStack_iteratorHasMore( MPE_CallStack_t *cstk )
72 {
73     char *line_end;
74     if ( fgets( cstk->line_buf, MPE_CALLSTACK_MAXLINE, cstk->pipefile ) ) {
75         line_end = strchr( cstk->line_buf, '\n' );
76         if ( line_end != NULL ) {
77             *line_end = '\0';
78             return 1;
79         }
80     }
81     /* Since no more callstack record, close the reading end of the pipe */
82     fclose( cstk->pipefile );
83     return 0;
84 }
85 
86 /*@
87     MPE_CallStack_iteratorFetchNext - Returns next frame in the
88                                       CallStack iterator.
89 
90     Input Parameters:
91 .   cstk   - Pointer to MPE_CallStack_t.
92 
93     Returns:
94     the next callstack string without the ending '\n'.
95 @*/
MPE_CallStack_iteratorFetchNext(MPE_CallStack_t * cstk)96 const char* MPE_CallStack_iteratorFetchNext( MPE_CallStack_t *cstk )
97 {
98     return (const char *) (cstk->line_buf);
99 }
100