This is the mail archive of the gdb@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: gdb: detection and/or fork+gethostbyname crash workaround?


To the other reply: well, I can already manually disable DNS
forking; I just don't want to have to do that.

On Tue, Jul 24, 2001 at 01:26:07PM -0700, Kevin Buettner wrote:
> > On Tue, Jul 24, 2001 at 08:52:19AM -0700, Kevin Buettner wrote:
> > > If it's one which uses ptrace(), the kernel usually prohibits two
> > > processes from invoking ptrace() on the same inferior.  So one
> > > strategy might be to have the program in question cause ptrace to be
> > > invoked on itself.  I don't think the process will be able to do this
> > > itself; I think it's likely that it would have to fork and let the
> > > child attempt this.  The return status from wait() or waitpid() could
> > > indicate whether the attempt to invoke ptrace() was successful or not.
> > 
> > That's what I tried (x86 Linux); a process can't ptrace itself.  I could
> > fork a process to test this, I suppose; I'll try that.  (Wouldn't it
> > be the return status from ptrace(), though?  I assume it'd return something
> > like EPERM if a process is already being debugged.)
> 
> Right; you'd pass back the results of the attempted ptrace() (and it
> looks to me like EPERM is the right thing to test for) through the
> child's exit status.  That's why I said you'd use wait() or waitpid()
> to determine it.

Got it.  In case anyone else wants it (or can point out an error, of course):

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <assert.h>

#include <sys/ptrace.h>
#include <signal.h>

#include <sys/types.h>
#include <sys/wait.h>

bool in_debugger()
{
	int cpid = fork();
	assert(cpid != -1);

	if(cpid == 0) {
		signal(SIGCHLD, SIG_IGN);
		if(ptrace(PTRACE_ATTACH, getppid(), NULL, NULL) == -1) {
			/* Attach failed; it's probably already being debugged. */
			if(errno != EPERM)
				fprintf(stderr, "c ptrace: unexpected error: %s\n", strerror(errno));
			exit(1);
		}
		
		/* We just SIGSTOPped it; we need to CONT it now. */
		int ret;
		waitpid(getppid(), &ret, 0);

		if(ptrace(PTRACE_DETACH, getppid(), NULL, NULL) == -1)
			fprintf(stderr, "detach failed: %s\n", strerror(errno));

		kill(getppid(), SIGCONT);

		exit(0);
	}
	int ret;
	waitpid(cpid, &ret, 0);
	assert(!WIFSIGNALED(ret));

	return WEXITSTATUS(ret) != 0;

}

main()
{
	printf("%i\n", in_debugger());
}


>     1) Set up a signal handler in the child for SIGTRAP.  Have the
>        signal handler replace the trap instruction with a nop prior
>        to returning.

I tried that, with no luck.  I might have botched something silly, of course.

>     2) In the parent, call dlopen() to explicitly load the shared
>        libraries needed by gethostbyname().  That way, when
>        gethostbyname() is called, there won't be any unloaded
>        functions.

That'd mean searching out NSS libraries, and loading *all* of them ... and
there's no real guarantee that they're even in /lib.

-- 
Glenn Maynard


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]