[Bug 681071] Re: init: PTRACE_EVENT_CLONE not handled in fork tracking

Steve Langasek steve.langasek at canonical.com
Tue Feb 28 23:59:24 UTC 2012


FWIW, here's the ptrace(2) explanation of the PTRACE_O_TRACECLONE
option:

                     This  option  may  not  catch clone(2) calls in all cases.  If the
                     child calls clone(2) with  the  CLONE_VFORK  flag,
                     PTRACE_EVENT_VFORK will be delivered instead if
                     PTRACE_O_TRACEVFORK is  set;  otherwise if the child calls
                     clone(2) with the exit signal set to SIGCHLD,
                     PTRACE_EVENT_FORK  will  be  delivered   if
                     PTRACE_O_TRACEFORK is set.

So we should only need to trace clone() if we care about clones that
neither set CLONE_VFORK nor have the exit signal set to SIGCHLD.  And
all such clones are *not* separate processes for our purposes, but
threads, AFAICS.

So I agree that this is most likely invalid.  Clint, did you manage to
get corosync sorted out?

** Changed in: upstart (Ubuntu Precise)
       Status: Triaged => Incomplete

** Changed in: upstart
       Status: Triaged => Incomplete

-- 
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to upstart in Ubuntu.
https://bugs.launchpad.net/bugs/681071

Title:
  init: PTRACE_EVENT_CLONE not handled in fork tracking

Status in Upstart:
  Incomplete
Status in “upstart” package in Ubuntu:
  Incomplete
Status in “upstart” source package in Precise:
  Incomplete

Bug description:
  corosync seems to use 'clone' instead of 'fork' to daemonize. Here is
  its startup strace to demonstrate:

  10709 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"0\0\0\0\24\0\2\0\274O\354L\325)\0\0\2\10\200\376\1\0\0\0\10\0\1\0\177\0\0\1"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 224
  10709 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"@\0\0\0\24\0\2\0\274O\354L\325)\0\0\n\200\200\376\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 320
  10709 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0\274O\354L\325)\0\0\0\0\0\0\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 20
  10709 close(3)                          = 0
  10709 socket(PF_NETLINK, SOCK_RAW, 0)   = 3
  10709 bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
  10709 getsockname(3, {sa_family=AF_NETLINK, pid=10709, groups=00000000}, [12]) = 0
  10709 sendto(3, "\24\0\0\0\26\0\1\3\274O\354L\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
  10709 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"0\0\0\0\24\0\2\0\274O\354L\325)\0\0\2\10\200\376\1\0\0\0\10\0\1\0\177\0\0\1"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 224
  10709 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"@\0\0\0\24\0\2\0\274O\354L\325)\0\0\n\200\200\376\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 320
  10709 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0\274O\354L\325)\0\0\0\0\0\0\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 20
  10709 close(3)                          = 0
  10709 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fa2c17029d0) = 10710
  10710 setsid()                          = 10710
  10710 open("/dev/null", O_RDWR)         = 3
  10710 dup2(3, 0)                        = 0
  10710 dup2(3, 1)                        = 1
  10710 dup2(3, 2)                        = 2
  10710 close(3)                          = 0
  10710 mmap(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7fa2be6e8000
  10710 mprotect(0x7fa2be6e8000, 4096, PROT_NONE) = 0
  10710 clone(child_stack=0x7fa2beee7ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fa2beee89e0, tls=0x7fa2beee8710, child_tidptr=0x7fa2beee89e0) = 10711
  10710 futex(0x7fa2c12c30c4, FUTEX_WAIT_PRIVATE, 1, NULL <unfinished ...>
  10711 set_robust_list(0x7fa2beee89f0, 0x18 <unfinished ...>
  10709 exit_group(0)                     = ?

  In the above example, 10710 is the process that should be traced as
  the daemon.

  I think this may be ptrace getting outsmarted somehow. It normally
  will fire off a PTRACE_EVENT_FORK even if it shows as a clone syscall,
  but in this case, it doesn't. I'll attach this little hacky ptracing
  program that demonstraces where PTRACE_EVENT_CLONE gets fired before
  PTRACE_EVENT_FORK.

  # ./test /usr/sbin/corosync
  parent waiting for pid #29995 at line 74
  child running ptrace at line 89
  PTRACE_TRACEME successful
  TRAP received..0
  TRAP: caught, new pid=0
  TRAP: FIRST child...
  TRAP: 29995 did a (unknown)
  parent waiting for pid #29995 at line 74
  TRAP received..0
  TRAP: caught, new pid=29996
  TRAP: 29996 did a (unknown)
  parent waiting for pid #29995 at line 74
  TRAP received..3
  TRAP: caught, new pid=29996
  TRAP: 29996 did a clone
  parent waiting for pid #29995 at line 74
  TRAP received..1
  TRAP: caught, new pid=29996
  TRAP: cannot ptrace 29996: No such process
  TRAP: 29996 did a fork
  parent waiting for pid #29995 at line 74

  I think it might be worth working on a minimal patch that is back
  portable to previous versions of upstart so they can track daemons
  that do this.

  The end result of this, btw, is not that corosync is shown to have
  died, but that corosync's children are all tracked as the service
  itself, causing a 'stop corosync' to send SIGTERM to all of corosync's
  services, which is incorrect behavior quite obviously.

To manage notifications about this bug go to:
https://bugs.launchpad.net/upstart/+bug/681071/+subscriptions




More information about the foundations-bugs mailing list