To complete the port of some library to Cygwin, I need a way to produce
a traceback with as much info as possible. Currently I have something
that works but not that well.  There are basically 3 parts:

* Gather all the stack frames; see below.
* Assign the PCs in each frame to some executable image; done via dlfcn.
To be discussed later.
* Convert the PCs to function+source+line; done via addr2line. Ditto.

Despite a lot of web digging I have not (yet?) found a better way than
this classic unixish song-and-dance:

int
backtrace(void** buf, int bufsiz)
{
        int             res;
        int             p[2];
        pid_t           child;
        FILE*           thePipe = (NULL);
        char            line[1024];
        void*           unused;
        if (pipe(p) < 0){
                debug(-1, "*** Pipe() failed\n");
                return -1;
        }
        if ((child=fork())<0) {
                debug(-1, "*** Fork() failed\n");
                return -1;
        } else if (child == 0) {
                // In child. Make p[1] its stderr
                close(0);
                close(1);
                dup2 (p[1], 2);
                close (p[0]);
                close (p[1]);
                cygwin_stackdump();
                exit(0);
        }
        // In our process. Read from the pipe.
        close (p[1]);
        if((thePipe=fdopen(p[0], "rb"))==NULL) {
                debug(-1, "*** fdopen failed\n");
                return -1;
        }
        res = 0;
        while(fgets(line, sizeof(line), thePipe)) {
                if(res>=bufsiz)
                        break;
                while(isspace(line[strlen(line)-1]))
                        line[strlen(line)-1]=0;
                if(strcmp(line, "Stack trace:")==0 ||
                        strncmp(line, "Frame", 5)==0)
                        continue;
                if(strcmp(line, "End of stack trace")==0)
                        break;
                if(sscanf(line, "%8X %8X", (int*)&unused,
(int*)(buf+res))!=2) {
                        debug(-1, "*** sscanf failed\n");
                        return -1;
                }
                res++;
        }
        fclose(thePipe);
        return res;
}

Where debug(-1,...) is essentially fprintf(stderr,...).

Now this is acceptable for a traceback following the raising of some
error condition, but seems much too heavy for using in a leak detector.
Does anyone know of an equivalent API under cygwin? Or could we consider
adding such a variation of cygwin_stackdump to the cygwin DLL?

TiA
Michel Bardiaux

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply via email to