mwrap (Perl version) user+dev discussion/patches/pulls/bugs/help
 help / color / mirror / code / Atom feed
From: Eric Wong <e@80x24.org>
To: mwrap-perl@80x24.org
Subject: [PATCH 3/3] various documentation updates
Date: Fri, 16 Dec 2022 14:39:33 +0000	[thread overview]
Message-ID: <20221216143933.22430-4-e@80x24.org> (raw)
In-Reply-To: <20221216143933.22430-1-e@80x24.org>

mwrap_httpd will have online help :>
---
 httpd.h             | 29 ++++++++++++----
 script/mwrap-perl   | 78 +++++++++++++++++++++++++++++++++++++++++
 script/mwrap-rproxy | 84 ++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 180 insertions(+), 11 deletions(-)

diff --git a/httpd.h b/httpd.h
index fc7b873..afce2a1 100644
--- a/httpd.h
+++ b/httpd.h
@@ -483,7 +483,7 @@ static off_t write_loc_name(FILE *fp, const struct src_loc *l)
 		if (!s) return -1;
 		if (l->f) fputc('\n', fp);
 
-		/* omit local " [$ADDRESS]" if doing deep backtraces */
+		/* omit local " [RETURN_ADDRESS]" if doing deep backtraces */
 		for (uint32_t i = 0; i < l->bt_len; ++i) {
 			char *c = memrchr(s[i], '[', strlen(s[i]));
 			if (c && c > (s[i] + 2) && c[-1] == ' ')
@@ -723,12 +723,29 @@ static enum mw_qev pid_root(struct mw_h1 *h1, struct mw_h1req *h1r)
 	if (!fp) return h1_close(h1);
 #define default_min "2000"
 
-	FPUTS("<html><head><title>mwrap demo</title></head><body>"
-		"<p>mwrap demo", fp);
+	int pid = (int)getpid();
+	fprintf(fp, "<html><head><title>mwrap PID:%d</title></head><body>"
+		"<pre>mwrap PID:%d", pid, pid);
 	show_stats(fp);
-	FPUTS("<p><a\nhref=\"each/" default_min "\">allocations &gt;"
-		default_min " bytes</a>"
-		"<p><a\nhref=\"" URL "\">" URL "</a></body></html>", fp);
+	FPUTS("\n\n<a\nhref=\"each/" default_min "\">allocations &gt;"
+		default_min " bytes</a>""</pre><pre\nid=help>"
+"To get source file and line info for native backtraces, consult your\n"
+"distro for -dbg, -dbgsym, or -debug packages.\n"
+"And/or rebuild your code with debug flags (e.g. `-ggdb3' if using gcc)\n"
+"and don't strip the resulting binaries.\n"
+"You should see locations from the backtrace_symbols(3) function\n"
+"in the form of FILENAME(+OFFSET) or FILENAME(SYMBOL+OFFSET)\n"
+"(e.g. /usr/lib/foo.so(+0xdead) or /usr/lib/foo.so(func+(0xbeef))\n"
+"\n"
+"Any version of addr2line should decode FILENAME(+OFFSET) locations:\n"
+"\n"
+"	addr2line -e FILENAME OFFSET\n"
+"\n"
+"SYMBOL+OFFSET requires addr2line from GNU binutils 2.39+ (Aug 2022):\n"
+"\n"
+"	addr2line -e FILENAME SYMBOL+OFFSET\n", fp);
+
+	FPUTS("\n<a\nhref=\"" URL "\">" URL "</a></pre></body></html>", fp);
 	return h1_200(h1, &html, TYPE_HTML);
 #undef default_min
 }
diff --git a/script/mwrap-perl b/script/mwrap-perl
index 78e71e3..53eaa10 100644
--- a/script/mwrap-perl
+++ b/script/mwrap-perl
@@ -6,6 +6,10 @@ use Devel::Mwrap;
 my ($so) = grep(m!/Mwrap\.so\z!, @DynaLoader::dl_shared_objects);
 defined($so) or die 'Mwrap.so not loaded';
 my $cur = $ENV{LD_PRELOAD};
+if (!@ARGV || ($ARGV[0] // '') =~ /\A(?:-h|--help)\z/) {
+	require Pod::Usage;
+	Pod::Usage::pod2usage(@ARGV ? 0 : 1);
+}
 if (defined $cur) {
 	my @cur = split(/[: \t]+/, $cur);
 	if (!grep(/\A\Q$so\E\z/, @cur)) {
@@ -17,3 +21,77 @@ if (defined $cur) {
 	$ENV{LD_PRELOAD} = $so;
 }
 exec @ARGV;
+__END__
+=head1 NAME
+
+mwrap-perl - run any command under mwrap
+
+=head1 SYNOPSIS
+
+  # to trace a long-running program and access it via $DIRECTORY/$PID.sock:
+  MWRAP=socket_dir:$DIRECTORY mwrap-perl COMMAND
+
+  # to trace a short-lived command and dump its output to a log:
+  MWRAP=dump_path:$FILENAME mwrap-perl COMMAND
+
+=head1 DESCRIPTION
+
+mwrap-perl is a command-line to automatically add Mwrap.so as an
+LD_PRELOAD for any command.  It will resolve malloc-family calls
+to a Perl file and line number, and it can also provide a backtrace
+of native (C/C++) functions for non-Perl programs.
+
+=head1 ENVIRONMENT
+
+C<MWRAP> is the only environment variable read.  It contains multiple
+options delimited by C<,> with names and values delimited by C<:>
+
+=item socket_dir:$DIRECTORY
+
+This launches an embedded HTTP server in each process and binds it
+to C<$DIRECTORY/$PID.sock>.  C<curl --unix-socket $DIRECTORY/$PID.sock>
+or L<mwrap-rproxy(1p)> may be used to access various endpoints in
+the HTTP server.
+
+=item: bt:$DEPTH
+
+The backtrace depth for L<backtrace(3)> in addition to the Perl
+file and line number where C<$DEPTH> is a non-negative number.
+
+The maximum allowed value is 32, though values of 5 or less are
+typically useful.  Increasing this to even 2 or 3 can significantly
+increase the amount of memory mwrap (and liburcu) itself uses.
+
+This is only useful in conjunction with C<socket_dir>
+
+Default: 0
+
+=item dump_path:$FILENAME
+
+Dumps the output
+
+	total_bytes	call_count	location
+
+In the future, dumping to a self-describing CSV will be supported
+
+=back
+
+=head1 CONTACT
+
+Feedback welcome via plain-text mail to L<mailto:mwrap-perl@80x24.org>
+
+Mail archives are hosted at L<https://80x24.org/mwrap-perl/>
+
+=head1 COPYRIGHT
+
+Copyright all contributors L<mailto:mwrap-perl@80x24.org>
+
+License: GPL-2.0+ L<https://www.gnu.org/licenses/gpl-2.0.txt>
+
+Source code is at L<https://80x24.org/mwrap-perl.git/>
+
+=head1 SEE ALSO
+
+L<mwrap-rproxy(1)>, L<Devel::Mwrap(3pm)>
+
+=cut
diff --git a/script/mwrap-rproxy b/script/mwrap-rproxy
index 97cca8e..da5379a 100644
--- a/script/mwrap-rproxy
+++ b/script/mwrap-rproxy
@@ -4,14 +4,17 @@
 # thin wrapper for Devel::Mwrap::Rproxy
 use v5.12; # strict
 eval { require Plack::Runner } or die "Plack not installed: $@\n";
-require Devel::Mwrap::Rproxy;
 use Getopt::Long qw(:config no_ignore_case no_auto_abbrev pass_through);
 my $usage = "$0 --socket-dir=/path/to/socket-dir [PLACKUP_OPTIONS]\n";
-my $socket_dir;
-my $gz = 1;
-GetOptions('socket-dir=s' => \$socket_dir, 'deflate!' => \$gz) or die $usage;
+my %opt = (deflate => 1);
+GetOptions(\%opt, 'socket-dir=s', 'deflate!', 'help|h') or do {
+	require Pod::Usage; Pod::Usage::pod2usage(1);
+};
+if ($opt{help}) { require Pod::Usage; Pod::Usage::pod2usage(0) }
+my $socket_dir = delete $opt{'socket-dir'};
 $socket_dir //= ($ENV{MWRAP} // '') =~ m!\bsocket_dir:([^,]+)! ? $1 : undef;
 $socket_dir // die $usage;
+require Devel::Mwrap::Rproxy;
 my $rproxy = Devel::Mwrap::Rproxy->new($socket_dir);
 my $app = sub { $rproxy->call(@_) };
 my $runner = Plack::Runner->new;
@@ -28,7 +31,78 @@ Inherited socket (fd=3) is non-blocking, making it blocking.
 		$runner->set_options(listen_sock => $s);
 	}
 }
-if ($gz && eval { require Plack::Middleware::Deflater } and !$@) {
+if ($opt{deflate} && eval { require Plack::Middleware::Deflater } and !$@) {
 	$app = Plack::Middleware::Deflater->wrap($app);
 }
 $runner->run($app);
+__END__
+=head1 NAME
+
+mwrap-rproxy - reverse proxy for embedded per-process mwrap httpd
+
+=head1 SYNOPSIS
+
+  # start the long-running COMMAND you wish to trace:
+  MWRAP=socket_dir:$DIRECTORY mwrap-perl COMMAND
+
+  # in a different terminal, point mwrap-proxy to the mwrap-perl socket_dir
+  mwrap-rproxy --socket-dir=$DIRECTORY -l 127.0.0.1:8080
+
+  # open http://127.0.0.1:8080/ in your favorite web browser:
+  w3m http://127.0.0.1:8080/
+
+=head1 DESCRIPTION
+
+B<mwrap-rproxy> is a PSGI reverse proxy to provide access
+via TCP to the native, Unix-socket-only httpd embedded inside
+mwrap core.  It provides a listing of process IDs of each process
+traced via mwrap.
+
+B<mwrap-rproxy> does not have a hard dependency on mwrap-perl itself,
+it exists to provide a convenient interface to programs being
+traced by mwrap-perl.
+
+=head1 OPTIONS
+
+=over 4
+
+=item --socket-dir=DIRECTORY
+
+If unset, it will attempt to parse C<socket_dir:> from the C<MWRAP>
+environment (see L<mwrap-perl(1p)>).
+
+=item --no-deflate
+
+L<Plack::Middleware::Deflater(3pm)> is loaded by default if available.
+Using C<--no-deflate> will save CPU cycles at the expe
+
+=back
+
+Additionally, all options in L<plackup(1p)> are supported.  Notably,
+C<-l>/C<--listen> and C<--path=/prefix> may be useful.
+
+=head1 ENVIRONMENT
+
+mwrap-rproxy supports systemd (and compatible) socket activation via
+C<LISTEN_PID> and C<LISTEN_FDS> variables.  See L<systemd.socket(5)>
+and L<sd_listen_fds(3)>.
+
+=head1 CONTACT
+
+Feedback welcome via plain-text mail to L<mailto:mwrap-perl@80x24.org>
+
+Mail archives are hosted at L<https://80x24.org/mwrap-perl/>
+
+=head1 COPYRIGHT
+
+Copyright all contributors L<mailto:mwrap-perl@80x24.org>
+
+License: GPL-2.0+ L<https://www.gnu.org/licenses/gpl-2.0.txt>
+
+Source code is at L<https://80x24.org/mwrap-perl.git/>
+
+=head1 SEE ALSO
+
+L<mwrap-perl(1p)>
+
+=cut

      parent reply	other threads:[~2022-12-16 14:39 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-16 14:39 [PATCH 0/3] fleshing out some things Eric Wong
2022-12-16 14:39 ` [PATCH 1/3] support changing bt_req_depth dynamically Eric Wong
2022-12-16 14:39 ` [PATCH 2/3] support symlink install Eric Wong
2022-12-16 14:39 ` Eric Wong [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221216143933.22430-4-e@80x24.org \
    --to=e@80x24.org \
    --cc=mwrap-perl@80x24.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mwrap-perl.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).