Re: Profile disappears when process ends



On Sat, 2003-09-20 at 08:55, Owen Taylor wrote:
> On Sat, 2003-09-20 at 00:33, Harry Tily wrote:
> > Hi
> > 
> > I'm trying to figure out how to use memprof (isn't there anyone on this
> > list who can use it and has time to write a very brief manual?) I've
> > managed to get my process running and generate its profile and leak
> > information, but as soon as the process ends, all that data vanishes
> > again. This only gives me a few seconds to look at the output and try to
> > work out what's happening. How do I keep the information on screen?
> 
> With recent versions of glibc, the code in memprof to keep the child
> from exiting stopped working. I haven't tracked the problem down ...
> what you can do is simply put a sleep(3600) at the end of your
> main routine.

Just put a fix/workaround for this into CVS:

Sat Sep 20 10:52:06 2003  Owen Taylor  <otaylor redhat com>
 
        * intercept.c): Switch to atexit() as the primary means
        of intercepting exiting. It isn't as good as interposing _exit,
        but interposing _exit doesn't work with newer versions of
        GNU libc.

Regards,
						Owen

Index: intercept.c
===================================================================
RCS file: /cvs/gnome/memprof/intercept.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -p -r1.1 -r1.2
--- intercept.c	5 Sep 2002 19:16:38 -0000	1.1
+++ intercept.c	20 Sep 2003 14:54:16 -0000	1.2
@@ -55,6 +55,7 @@ typedef struct {
 static void new_process (ThreadInfo *thread,
 			 pid_t       old_pid,
 			 MIOperation operation);
+static void atexit_trap (void);
 
 static int (*old_execve) (const char *filename,
 			  char *const argv[],
@@ -76,7 +77,7 @@ static ThreadInfo threads[MAX_THREADS];
 static char *socket_path = NULL;
 static unsigned int seqno = 0;
 
-#undef ENABLE_DEBUG
+#define ENABLE_DEBUG
 
 #ifdef ENABLE_DEBUG
 #define MI_DEBUG(arg) mi_debug arg
@@ -170,6 +171,8 @@ initialize ()
 	old_clone = dlsym(RTLD_NEXT, "__clone");
 	old__exit = dlsym(RTLD_NEXT, "_exit");
 
+	atexit (atexit_trap);
+
 	mi_init ();
 	initialized = 1;
 }
@@ -470,42 +473,64 @@ int clone (int (*fn) (void *arg),
 	return __clone (fn, child_stack, flags, arg);
 }
 
+static void
+exit_wait (void)
+{
+	MIInfo info;
+	ThreadInfo *thread;
+	int count;
+	char response;
+	info.any.operation = MI_EXIT;
+	info.any.seqno = seqno++;
+	info.any.pid = getpid();
+	
+	mi_stop ();
+	
+	thread = find_thread (info.any.pid);
+	
+	if (mi_write (thread->outfd, &info, sizeof (MIInfo)))
+		/* Wait for a response before really exiting
+		 */
+		while (1) {
+			count = read (thread->outfd, &response, 1);
+			if (count >= 0 || errno != EINTR)
+				break;
+		}
+	
+	close (thread->outfd);
+	thread->pid = 0;
+	release_thread (thread);
+}
+
+/* Because _exit() isn't interposable in recent versions of
+ * GNU libc, we can't depend on this, and instead use the less-good
+ * atexit_trap() below. But we leave this here just in case we
+ * are using an old version of libc where _exit() is interposable,
+ * so we can trap a wider range of exit conditions
+ */
 void
 _exit (int status)
 {
 	if (initialized <= 0)
-		abort_unitialized ("exit");
+		abort_unitialized ("_exit");
 
-	MI_DEBUG (("Exiting\n"));
+	MI_DEBUG (("_Exiting\n"));
 	
 	if (tracing) {
-		MIInfo info;
-		ThreadInfo *thread;
-		int count;
-		char response;
-		info.any.operation = MI_EXIT;
-		info.any.seqno = seqno++;
-		info.any.pid = getpid();
-
-		mi_stop ();
-
-		thread = find_thread (info.any.pid);
-		
-		if (mi_write (thread->outfd, &info, sizeof (MIInfo)))
-			/* Wait for a response before really exiting
-			 */
-			while (1) {
-				count = read (thread->outfd, &response, 1);
-				if (count >= 0 || errno != EINTR)
-					break;
-			}
-
-		close (thread->outfd);
-		thread->pid = 0;
-		release_thread (thread);
+		exit_wait ();
+		tracing = 0;
 	}
 
 	(*old__exit) (status);
+}
+
+static void
+atexit_trap (void)
+{
+	if (tracing) {
+		exit_wait ();
+		tracing = 0;
+	}
 }
 
 static void construct () __attribute__ ((constructor));


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]