Let''s say that I want to trace the first write system call after an open, but ignore any following calls of the same type. Closing and re-opening the file should re-activate the trace. Is there an easy way to do this? -r -- http://www.cfcl.com/rdm Rich Morin http://www.cfcl.com/rdm/resume rdm at cfcl.com http://www.cfcl.com/rdm/weblog +1 650-873-7841 Technical editing and writing, programming, and web development
On Sun, May 28, 2006 at 01:33:16PM -0700, Rich Morin wrote:> Let''s say that I want to trace the first write system call > after an open, but ignore any following calls of the same > type. Closing and re-opening the file should re-activate > the trace. Is there an easy way to do this?It depends on what you mean by the "same type", but yes, this is easy to do with DTrace. The specific script will depend on the exact nature of your question: do you want to know the first write system call made by the same thread that did the open, or any thread? And presumably you are interested in a particular file? While the best tools available in DTrace for the job depend on the specific version of Solaris you''re running (Solaris 10, Solaris 10 Update 1, or the latest OpenSolaris/Solaris Express), here''s a script that will answer the question on all of them, for all files: ---8<--- firstwrite.d ---8<--- #!/usr/sbin/dtrace -s #pragma D option quiet syscall::open*:entry { self->name = arg0; } syscall::open*:return /errno == 0 && self->name != NULL/ { watching[curpsinfo->pr_addr, arg1] = copyinstr(self->name); } syscall::write*:entry /watching[curpsinfo->pr_addr, arg0] != NULL/ { printf("thread %d in pid %d (%s) writes to %s (fd %d)\n", tid, pid, execname, watching[curpsinfo->pr_addr, arg0], arg0); watching[curpsinfo->pr_addr, arg0] = NULL; } ---8<--- firstwrite.d ---8<--- Running this on my laptop: # chmod +x firswrite.d # ./firstwrite.d thread 1 in pid 953 (xterm) writes to /lib/libnsl.so.1 (fd 3) thread 1 in pid 956 (utmp_update) writes to /var/adm/utmpx (fd 9) thread 1 in pid 956 (utmp_update) writes to /etc/utmppipe (fd 10) thread 1 in pid 953 (xterm) writes to /dev/ptmx (fd 5) thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) thread 1 in pid 989 (firefox-bin) writes to /tmp/.X11-pipe/X0 (fd 5) thread 1 in pid 989 (firefox-bin) writes to /tmp/.X11-pipe/X0 (fd 7) thread 2 in pid 671 (firefox-bin) writes to /dev/udp (fd 36) ... Note that this is _only_ getting write(2) (and variants), and it''s _only_ getting them after an open(2). If one writes to a file in a different way (e.g., via mmap(2)), or gets the file descriptor in some other fashion (e.g., on a dup(2)), it won''t show up here. There are ways to capture those variants too, of course -- it just depends on what you''re seeking to understand... - Bryan -------------------------------------------------------------------------- Bryan Cantrill, Solaris Kernel Development. http://blogs.sun.com/bmc
> Running this on my laptop: > > # chmod +x firswrite.d > # ./firstwrite.d > thread 1 in pid 953 (xterm) writes to /lib/libnsl.so.1 (fd 3) > thread 1 in pid 956 (utmp_update) writes to /var/adm/utmpx (fd 9) > thread 1 in pid 956 (utmp_update) writes to /etc/utmppipe (fd 10) > thread 1 in pid 953 (xterm) writes to /dev/ptmx (fd 5) > thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) > thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) > thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) > thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) > thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) > thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) > thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) > thread 1 in pid 1 (init) writes to /etc/svc/volatile/init-next.state (fd 1) > thread 1 in pid 989 (firefox-bin) writes to /tmp/.X11-pipe/X0 (fd 5) > thread 1 in pid 989 (firefox-bin) writes to /tmp/.X11-pipe/X0 (fd 7) > thread 2 in pid 671 (firefox-bin) writes to /dev/udp (fd 36) > ... > > Note that this is _only_ getting write(2) (and variants), and it''s _only_ > getting them after an open(2). If one writes to a file in a different > way (e.g., via mmap(2)), or gets the file descriptor in some other fashion > (e.g., on a dup(2)), it won''t show up here.As it turns out, the presence of those variants also resulted in false positives: if a file descriptor is opened, closed, and then allocated through some other means (dup(2), socket(2), etc.), the write to the file descriptor will be falsely reported as a write to the file. To fix this, a syscall::close:entry clause must be added. The corrected script: ---8<--- firstwrite.d ---8<--- #!/usr/sbin/dtrace -s #pragma D option quiet syscall::open*:entry { self->name = arg0; } syscall::open*:return /errno == 0 && self->name != NULL/ { watching[curpsinfo->pr_addr, arg1] = copyinstr(self->name); } syscall::close:entry { watching[curpsinfo->pr_addr, arg0] = NULL; } syscall::write*:entry /watching[curpsinfo->pr_addr, arg0] != NULL/ { printf("thread %d in pid %d (%s) writes to %s (fd %d)\n", tid, pid, execname, watching[curpsinfo->pr_addr, arg0], arg0); watching[curpsinfo->pr_addr, arg0] = NULL; } ---8<--- firstwrite.d ---8<--- If you''re running on Solaris 10 Update 1 or later, I strongly recommend using the fds[] array to get out of these difficulties of following file descriptors. For example, a reliable way of tracking write(2)s by filename: # dtrace -n syscall::write:entry''{@[fds[arg0].fi_pathname] = count()}'' Much easier than chasing all of the system calls that manipulate file descriptors... - Bryan -------------------------------------------------------------------------- Bryan Cantrill, Solaris Kernel Development. http://blogs.sun.com/bmc
przemolicc at poczta.fm
2006-May-29 07:36 UTC
[dtrace-discuss] Conditional tracing of system calls
On Sun, May 28, 2006 at 11:13:25PM -0700, Bryan Cantrill wrote:> > If you''re running on Solaris 10 Update 1 or later, I strongly recommend > using the fds[] array to get out of these difficulties of following file > descriptors. For example, a reliable way of tracking write(2)s by > filename: > > # dtrace -n syscall::write:entry''{@[fds[arg0].fi_pathname] = count()}'' > > Much easier than chasing all of the system calls that manipulate file > descriptors...Is there any document/web page which will "trace" ;-) all the changes in DTrace in each Solaris 10 release (even coming) ? I''d like to see the changes from sysadmin/programmer point of view (the example above is good): DTrace in S 10 GA ... syscall::write:entry { ... } could be written in DTrace in S 10 U1 ... syscall::write:entry { ... } Maybe such doc could also include changes in Solaris Express/ OpenSOlaris as well ? Regards przemol
On Mon, May 29, 2006 at 09:36:18AM +0200, przemolicc at poczta.fm wrote:> Is there any document/web page which will "trace" ;-) all the changes in DTrace > in each Solaris 10 release (even coming) ? I''d like to see the changes > from sysadmin/programmer point of view (the example above is good):That''s something we''ve been meaning to do. We''ll try to put something together when we get some time. Adam -- Adam Leventhal, Solaris Kernel Development http://blogs.sun.com/ahl