wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

backtrace.c (1515B)


      1 /* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
      2  * See LICENSE file for license details.
      3  */
      4 #include <sys/types.h>
      5 #include <sys/stat.h>
      6 #include <sys/wait.h>
      7 #include <fcntl.h>
      8 #include <signal.h>
      9 
     10 #include <bio.h>
     11 #include <plan9.h>
     12 #undef nelem
     13 #include <stuff/util.h>
     14 #include "debug.h"
     15 
     16 #ifdef __linux__
     17 # define PROGTXT "exe"
     18 #else
     19 # define PROGTXT "file"
     20 #endif
     21 
     22 static void
     23 _backtrace(int pid, char *btarg) {
     24 	char *proc, *spid, *gdbcmd;
     25 	int fd[3], p[2];
     26 	int status, cmdfd;
     27 
     28 	gdbcmd = estrdup("/tmp/gdbcmd.XXXXXX");
     29 	if(pipe(p) < 0)
     30 		goto done;
     31 	closeexec(p[0]);
     32 
     33 	cmdfd = mkstemp(gdbcmd);
     34 	if(cmdfd < 0)
     35 		goto done;
     36 
     37 	fprint(cmdfd, "bt %s\n", btarg);
     38 	fprint(cmdfd, "detach\n");
     39 	close(cmdfd);
     40 
     41 	fd[0] = open("/dev/null", O_RDONLY);
     42 	fd[1] = p[1];
     43 	fd[2] = dup(2);
     44 
     45 	proc = sxprint("/proc/%d/" PROGTXT, pid);
     46 	spid = sxprint("%d", pid);
     47 	if(spawn3l(fd, "gdb", "gdb", "-batch", "-x", gdbcmd, proc, spid, nil) < 0) {
     48 		unlink(gdbcmd);
     49 		goto done;
     50 	}
     51 
     52 	Biobuf bp;
     53 	char *s;
     54 
     55 	Binit(&bp, p[0], OREAD);
     56 	while((s = Brdstr(&bp, '\n', 1))) {
     57 		Dprint(DStack, "%s\n", s);
     58 		free(s);
     59 	}
     60 	unlink(gdbcmd);
     61 
     62 done:
     63 	free(gdbcmd);
     64 	kill(pid, SIGKILL);
     65 	waitpid(pid, &status, 0);
     66 }
     67 
     68 void
     69 backtrace(char *btarg) {
     70 	int pid;
     71 
     72 	/* Fork so we can backtrace the child. Keep this stack
     73 	 * frame minimal, so the trace is fairly clean.
     74 	 */
     75 	Debug(DStack)
     76 		switch(pid = fork()) {
     77 		case -1:
     78 			return;
     79 		case 0:
     80 			kill(getpid(), SIGSTOP);
     81 			_exit(0);
     82 		default:
     83 			_backtrace(pid, btarg);
     84 			break;
     85 		}
     86 
     87 }