diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2012-03-17 01:24:25 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2012-03-17 01:24:25 +0100 |
commit | cb419c52cb861beeadd7b94f1aa4f0fd8884eacf (patch) | |
tree | cf4873bb0fa6785dbbe7dcb5aa9bf52668c0f600 /test | |
parent | b468f2320a8b8e245b481c78b58431ac56505849 (diff) | |
download | strace-cb419c52cb861beeadd7b94f1aa4f0fd8884eacf.tar.gz strace-cb419c52cb861beeadd7b94f1aa4f0fd8884eacf.tar.bz2 strace-cb419c52cb861beeadd7b94f1aa4f0fd8884eacf.tar.xz |
test/threaded_execve: make it also test a case when leader is not in syscall
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/threaded_execve.c | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/test/threaded_execve.c b/test/threaded_execve.c index 9cf3dae..628589a 100644 --- a/test/threaded_execve.c +++ b/test/threaded_execve.c @@ -10,24 +10,24 @@ * * # Should not be confused by traced execve-ing thread * # replacing traced leader: - * [LEADER_EXIT=1] strace -oLOG -f ./threaded_execve + * strace -oLOG -f ./threaded_execve * * # Same, but different output mode. Output after execve * # should go into leader's LOG.<pid> file, not into execve'ed * # thread's log file: - * [LEADER_EXIT=1] strace -oLOG -ff ./threaded_execve + * strace -oLOG -ff ./threaded_execve * * # Should not be confused by non-traced execve-ing thread * # replacing traced leader: - * [LEADER_EXIT=1] strace -oLOG ./threaded_execve - * ^^^^^^^^^^^^^^^^^^^^^ + * strace -oLOG ./threaded_execve + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * In Linux 3.2, non-traced execve-ing thread does not * become traced after execve, even though it has pid == leader's pid * after execve. And yet, strace's waitpid doesn't return ECHILD. * * # Run for NUM seconds, not just one second. * # Watch top to check for memory leaks in strace: - * [LEADER_EXIT=1] strace -oLOG -f ./threaded_execve <NUM> + * strace -oLOG -f ./threaded_execve <NUM> * */ #define NUM_THREADS 1 @@ -65,6 +65,7 @@ extern int __clone2(int (*fn) (void *), void *child_stack_base, #define syscall_exit(v) syscall(__NR_exit, (v)); static char my_name[PATH_MAX]; +static int leader_final_action; static int thread1(void *unused) @@ -77,18 +78,20 @@ thread1(void *unused) static int thread2(void *unused) { + char buf[64]; + sprintf(buf, "%d", leader_final_action); write(1, "2", 1); usleep(20*1000); /* This fails with ENOENT if leader has exited by now! :) */ - execl("/proc/self/exe", "exe", "exe", NULL); + execl("/proc/self/exe", "exe", "exe", buf, NULL); /* So fall back to resolved name */ - execl(my_name, "exe", "exe", NULL); + execl(my_name, "exe", "exe", buf, NULL); for(;;) pause(); return 0; } static void -thread_leader(int die) +thread_leader(void) { /* malloc gives sufficiently aligned buffer. * long buf[] does not! (on ia64). @@ -111,27 +114,31 @@ thread_leader(int die) | 0 /* no signal to send on death */ , NULL); - if (die) syscall_exit(42); - for(;;) pause(); + /* Various states leader can be while other thread execve's: */ + switch (leader_final_action % 3) { + case 0: syscall_exit(42); /* leader is dead */ + case 1: for(;;) pause(); /* leader is in syscall */ + default: for(;;) continue; /* leader is in userspace */ + } } int main(int argc, char **argv) { - int die = getenv("LEADER_EXIT") != NULL; - if (readlink("/proc/self/exe", my_name, sizeof(my_name)-1) <= 0) return 1; setbuf(stdout, NULL); - if (argv[1] && strcmp(argv[1], "exe") == 0) - thread_leader(die); + if (argv[1] && strcmp(argv[1], "exe") == 0) { + leader_final_action = atoi(argv[2]) + 1; + thread_leader(); + } printf("%d: thread leader\n", getpid()); alarm(argv[1] ? atoi(argv[1]) : 1); - thread_leader(die); + thread_leader(); return 0; } |