Home | History | Annotate | Line # | Download | only in dist
      1 #!/usr/pkg/bin/perl
      2 #
      3 # errinfo - report on syscall failures and print errno error messages.
      4 #	    Written using Perl and DTrace (Solaris 10 03/05)
      5 #
      6 # When system calls fail, an errno variable is set to convay a meaningful
      7 # message to the end user - so long as the program does something with it
      8 # (eg, "ls" printing "No such file or directory"). This program fetches
      9 # and prints details for all syscall failures along with their message,
     10 # whether the failing program is already printing this info or not.
     11 #
     12 # $Id: errinfo,v 1.2 2016/12/12 16:30:03 christos Exp $
     13 #
     14 # USAGE:	errinfo [-ch] [-p PID] [-n name]
     15 #
     16 #		-c		# counts - aggregate style
     17 #		-p PID		# examine this PID only
     18 #		-n name		# examine processes with this name only
     19 #	eg,
     20 #		errinfo			# default output - snoop event style
     21 #		errinfo -n ssh		# examine "ssh" processes only
     22 #		errinfo -cn ssh		# examine "ssh" using counts
     23 #
     24 # FIELDS:
     25 #		EXEC		Program name (truncated)
     26 #		SYSCALL		System call name
     27 #		ERR		Value of errno
     28 #		DESC		Description of errno message
     29 #
     30 # SEE ALSO:	/usr/include/sys/errno.h
     31 #
     32 # COPYRIGHT: Copyright (c) 2005, 2006 Brendan Gregg.
     33 #
     34 # CDDL HEADER START
     35 #
     36 #  The contents of this file are subject to the terms of the
     37 #  Common Development and Distribution License, Version 1.0 only
     38 #  (the "License").  You may not use this file except in compliance
     39 #  with the License.
     40 #
     41 #  You can obtain a copy of the license at Docs/cddl1.txt
     42 #  or http://www.opensolaris.org/os/licensing.
     43 #  See the License for the specific language governing permissions
     44 #  and limitations under the License.
     45 #
     46 # CDDL HEADER END
     47 #
     48 # Author: Brendan Gregg  [Sydney, Australia]
     49 #
     50 # 18-Apr-2005   Brendan Gregg   Created this.
     51 # 20-Apr-2006	   "      "	Last update.
     52 #
     53 
     54 use Getopt::Std;
     55 
     56 #
     57 #  Defaults
     58 #
     59 $FILTER = "";
     60 $COUNT = 0;
     61 
     62 #
     63 #  Command line arguments
     64 #
     65 &Usage() if $ARGV[0] eq "--help";
     66 getopts('ch:n:p:') || &Usage();
     67 &Usage() if $opt_h;
     68 $COUNT = 1 if $opt_c;
     69 $FILTER = "&& execname == \"$opt_n\"" if defined $opt_n;
     70 $FILTER = "&& pid == $opt_p" if defined $opt_p;
     71 
     72 #
     73 #  Load errno descriptions
     74 #
     75 open(ERRNO,"/usr/include/sys/errno.h") || die "ERROR1: reading errno.h: $!\n";
     76 while (chomp($line = <ERRNO>)) {
     77 	next unless $line =~ /^#define/;
     78 	($errno,$desc) = $line =~ /^#define\s+\S+\s+(\d+)\s+\/\*(.*)\*\//;
     79 	$Errno{$errno} = $desc;
     80 }
     81 close ERRNO;
     82 
     83 #
     84 #  Declare DTrace script
     85 #
     86  if ($COUNT) {		# aggregate style
     87 $dtrace = <<END;
     88 /usr/sbin/dtrace -n '
     89 	#pragma D option quiet
     90 	syscall:::return 
     91 	/errno != 0 && pid != \$pid $FILTER/ 
     92 	{ 
     93 		\@Errs[execname, probefunc, errno] = count(); 
     94 	}
     95 	dtrace:::END {
     96 		printa("%s %s %d %\@d\\n", \@Errs);
     97 	}'
     98 END
     99  } else {		# snoop style
    100 $dtrace = <<END; 
    101 /usr/sbin/dtrace -n '
    102 	#pragma D option quiet
    103 	#pragma D option switchrate=5hz
    104 	syscall:::return 
    105 	/errno != 0 && pid != \$pid $FILTER/ 
    106 	{ 
    107 		printf("%s %s %d\\n", execname, probefunc, errno); 
    108 	}'
    109 END
    110  }
    111 
    112 #
    113 #  Cleanup on signals
    114 #
    115 $SIG{INT} = \&Cleanup_Signal;    # Ctrl-C
    116 $SIG{QUIT} = \&Cleanup_Signal;   # Ctrl-\
    117 $SIG{TERM} = \&Cleanup_Signal;   # TERM
    118 
    119 #
    120 #  Run DTrace, process output
    121 #
    122 
    123 if ($COUNT) {
    124 	print STDERR "Tracing... Hit Ctrl-C to end.\n";
    125 	$header = 1;
    126 } else {
    127 	printf("%16s %16s %4s  %s\n","EXEC","SYSCALL","ERR","DESC");
    128 }
    129 
    130 ### Open DTrace
    131 open(DTRACE,"$dtrace |") || die "ERROR2: Can't start dtrace (perms?): $!\n";
    132 
    133 ### Process DTrace output
    134 while (chomp($line = <DTRACE>)) {
    135 
    136 	### Print count header
    137 	if ($COUNT && $header) {
    138 		printf("\n%16s %16s %4s %6s  %s\n",
    139 		 "EXEC","SYSCALL","ERR","COUNT","DESC");
    140 		$header = 0;
    141 	}
    142 
    143 	### Split data
    144 	($execname,$syscall,$errno,$counts) = split(' ',$line);
    145 	next if $errno eq "";
    146 
    147 	### Fetch errno description
    148 	$desc = $Errno{$errno};
    149 
    150 	### Print output line
    151 	if ($COUNT) {
    152 		printf("%16s %16s %4d %6d %s\n",
    153 		 $execname,$syscall,$errno,$counts,$desc);
    154 	} else {
    155 		printf("%16s %16s %4d %s\n",$execname,$syscall,$errno,$desc);
    156 	}
    157 }
    158 close(DTRACE);
    159 
    160 #
    161 #  Triggered by signals
    162 #
    163 sub Cleanup_Signal {
    164 }
    165 
    166 #
    167 #  Usage message
    168 #
    169 sub Usage {
    170         print STDERR "USAGE: errinfo [-ch] [-p PID] [-n name]\n";
    171 	print STDERR <<ENDUSAGE;
    172      eg,
    173        errinfo       # default output - snoop event style
    174           -c         # counts - aggregate style
    175           -p 871     # examine PID 871 only
    176           -n ssh     # examine processes with the name "ssh" only
    177           -cn ssh    # examine "ssh" using counts
    178 ENDUSAGE
    179         exit(1);
    180 }
    181