From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13368 invoked by alias); 28 Apr 2008 11:55:08 -0000 Received: (qmail 13348 invoked by uid 22791); 28 Apr 2008 11:55:04 -0000 X-Spam-Status: No, hits=-0.2 required=5.0 tests=AWL,BAYES_50,J_CHICKENPOX_43,J_CHICKENPOX_63 X-Spam-Check-By: sourceware.org Received: from smtprelay0133.hostedemail.com (HELO smtprelay.hostedemail.com) (216.40.44.133) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 28 Apr 2008 11:54:37 +0000 Received: from filter.hostedemail.com (ff-bigip1 [10.5.19.254]) by smtprelay03.hostedemail.com (Postfix) with SMTP id B2A568504F; Mon, 28 Apr 2008 11:54:34 +0000 (UTC) X-SpamScore: 1 Received: from gnu.wildebeest.org (cc1341701-a.deven1.ov.home.nl [82.72.26.122]) (Authenticated sender: mark@klomp.org) by omf07.hostedemail.com (Postfix) with ESMTP; Mon, 28 Apr 2008 11:54:34 +0000 (UTC) Received: from [192.168.1.150] (helo=[192.168.1.29]) by gnu.wildebeest.org with esmtp (Exim 4.63) (envelope-from ) id 1JqRwE-0007gj-7e; Mon, 28 Apr 2008 13:54:33 +0200 Subject: Re: Reset breakpoints on fork (vfork followup) From: Mark Wielaard To: frysk Cc: Roland McGrath In-Reply-To: <1208883122.3426.18.camel@dijkstra.wildebeest.org> References: <1208883122.3426.18.camel@dijkstra.wildebeest.org> Content-Type: text/plain Date: Tue, 29 Apr 2008 18:25:00 -0000 Message-Id: <1209383669.3098.32.camel@dijkstra.wildebeest.org> Mime-Version: 1.0 X-Mailer: Evolution 2.12.3 (2.12.3-4.fc8) Content-Transfer-Encoding: 7bit X-Spam-Score: -4.2 (----) X-Spam-Summary: 11,1.093,0,e261535a30752bef,b7f2149f45db8cdd,mark@klomp.org,,RULES_HIT:2:125:355:379:541:599:601:800:945:960:967:973:988:989:1042:1260:1261:1277:1311:1313:1314:1345:1359:1373:1437:1515:1516:1518:1535:1605:1730:1747:1766:1792:1801:2110:2379:2393:2525:2560:2563:2682:2685:2693:2734:2857:2859:2892:2933:2937:2939:2942:2945:2947:2951:2954:3022:3027:3636:3865:3866:3867:3868:3869:3870:3871:3872:3873:3874:3934:3936:3938:3941:3944:3947:3950:4049:4118:4184:4321:4434:4605:5007:6117:6119:6261:7556:7652:7679:7903,0,RBL:none,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:,MSBL:none,DNSBL:none X-session-marker: 6D61726B406B6C6F6D702E6F7267 X-IsSubscribed: yes Mailing-List: contact frysk-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: frysk-owner@sourceware.org X-SW-Source: 2008-q2/txt/msg00065.txt.bz2 Hi, On Tue, 2008-04-22 at 18:52 +0200, Mark Wielaard wrote: > Roland, I CCed you in the hope that you could maybe point out some nice > way now or in the future to do this. The patch itself might not be very > interesting to you. The way we model Tasks and events means we do this > in three stages. First we get a fork event and capture all the > (software) breakpoint addresses, then we already create the Proc and > then the main Task based on the pid given in the event, then we wait for > an (stopped) event on this now Task, then we go over all the breakpoints > left and patch in the original instructions again. > > This of course isn't very efficient since I assume the kernel could help > us out here since it know the pages we touched through ptrace poke to > set the breakpoints in the first place. If there was some way to have an > event from the kernel where we got the forking and forked tasks in a > quiescent state (at the same time) and then could inspect both and tell > the kernel whether or not to copy the modified or original code pages > that would be much better. Bonus points for having advanced knowledge of > a pending exec event, which would wipe away any changes we do anyway > (although I don't see how this would be possible). A small followup without code, but hopefully enough information for someone to design the right setup to make it happen. There is also still the outstanding issue of frysk not handling vfork. http://sourceware.org/bugzilla/show_bug.cgi?id=1583 Getting events for vfork is not hard. In Ptrace.cxx we should also request PTRACE_O_TRACEVFORK and in Wait.cxx we should handle the PTRACE_EVENT_VFORK. This however does not bring us full vfork support. vfork() is a special kind of fork() that blocks the parent till the child process it just vforked calls exec(), the child process is not allowed to do much (see the vfork manual page) but between the vfork call and the exec call the child does share its memory pages with its parent. This makes our current approach to handling fork() not work for vfork(). If we alter any breakpoints in this new child before it calls exec() it will alter the parent's memory pages also. So if we alter any (software) breakpoints we need to track the state changes in the parent (which will be blocked itself). Luckily the kernel can give us some events to help with this all. In Ptrace.cxx we must request PTRACE_O_TRACEVFORKDONE and in Wait.cxx we must also handle PTRACE_EVENT_VFORK_DONE. Then we must put both child and parent into new states and track any breakpoint manipulation. I don't immediately see a clean way to handle fork and vfork the same way even though they are so similar to the user. It would be nice to have a way to express the TaskObserver.Forked in a way that the user of such an observer doesn't have to care about what kind of fork it is about. And to have it in such a way that the user of the observer can easily inspect/manipulate both parent and child. Currently it must handle two different events for parent and child, but it cannot assume that either the parent or the child is in a state which allows any inspection/manipulation. I did make a little change to the current vfork test to have the right counts (but didn't resolve it since the code isn't there yet, I tested it by doing the above changes to Wait.cxx and Ptrace.cxx and pretending the vfork is just another fork, but obviously it breaks when also doing breakpoint Code observers at the same time). 2008-04-28 Mark Wielaard * TestTaskForkedObserver.java (testTaskVforkObserver): Correct counts. Cheers, Mark Test patch: diff --git a/frysk-core/frysk/proc/TestTaskForkedObserver.java b/frysk-core/frys index 5990546..ada14bd 100644 --- a/frysk-core/frysk/proc/TestTaskForkedObserver.java +++ b/frysk-core/frysk/proc/TestTaskForkedObserver.java @@ -89,10 +89,10 @@ public class TestTaskForkedObserver extends TestLib { assertEquals("number of child processes created", 1, forkObserver.forkCount); - assertEquals("number of child processes destroyed", - 1, forkObserver.terminatedCount); - assertEquals("number of times fork observer added", - 2, forkObserver.addedCount()); + assertEquals("number of exits (includes initial process)", + 2, forkObserver.terminatedCount); + assertEquals("number of times fork+terminated observer added", + 2 + 2, forkObserver.addedCount()); } private void runForkTest(ForkObserver forkObserver, String[] argv) { Not-committed-and-wrong! fvork handling patch: diff --git a/frysk-sys/frysk/sys/cni/Wait.cxx b/frysk-sys/frysk/sys/cni/Wait.cxx index f902bb0..ce267d5 100644 --- a/frysk-sys/frysk/sys/cni/Wait.cxx +++ b/frysk-sys/frysk/sys/cni/Wait.cxx @@ -102,6 +102,9 @@ logWait(frysk::rsl::Log* logger, pid_t pid, int status, int case PTRACE_EVENT_FORK: wif_name = "WIFSTOPPED/FORK"; break; + case PTRACE_EVENT_VFORK: + wif_name = "WIFSTOPPED/VFORK"; + break; case PTRACE_EVENT_EXIT: wif_name = "WIFSTOPPED/EXIT"; break; @@ -168,6 +171,7 @@ processStatus(frysk::sys::ProcessIdentifier* pid, int status } break; case PTRACE_EVENT_FORK: + case PTRACE_EVENT_VFORK: try { // The event message contains the process-ID of the new // process. diff --git a/frysk-sys/frysk/sys/ptrace/cni/Ptrace.cxx b/frysk-sys/frysk/sys/ptr index 4aa12eb..5fa1654 100644 --- a/frysk-sys/frysk/sys/ptrace/cni/Ptrace.cxx +++ b/frysk-sys/frysk/sys/ptrace/cni/Ptrace.cxx @@ -137,7 +137,7 @@ frysk::sys::ptrace::Ptrace::optionTraceClone() { } jlong frysk::sys::ptrace::Ptrace::optionTraceFork() { - return PTRACE_O_TRACEFORK; + return PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK; } jlong frysk::sys::ptrace::Ptrace::optionTraceExit() {