diff options
author | Frank Ch. Eigler <fche@redhat.com> | 2019-08-10 12:39:42 -0400 |
---|---|---|
committer | Frank Ch. Eigler <fche@redhat.com> | 2019-08-10 12:39:42 -0400 |
commit | d724ba87a21fc3d43fff111ea1667b90d1f42e8c (patch) | |
tree | 724917a6284140777e907739f4d332eb06190de0 | |
parent | e657174526c0fa9d4680f5c080f644f5217b4500 (diff) | |
download | elfutils-d724ba87a21fc3d43fff111ea1667b90d1f42e8c.tar.gz |
dbgserver: snap
- support more specific posix error codes from dbgserver-find lookups
- accept presence or absence of traling slash in DBGSERVER_URL
- be able to run dbgserver-find.sh tests in check and installcheck mode
- run installcheck tests in dbgserver proper, by adding argp to dbgserver-find.c
-rw-r--r-- | dbgserver/Makefile.am | 19 | ||||
-rw-r--r-- | dbgserver/dbgserver-client.c | 38 | ||||
-rw-r--r-- | dbgserver/dbgserver-find.c | 53 | ||||
-rw-r--r-- | dbgserver/dbgserver.cxx | 10 | ||||
-rwxr-xr-x | tests/run-dbgserver-find.sh | 22 |
5 files changed, 116 insertions, 26 deletions
diff --git a/dbgserver/Makefile.am b/dbgserver/Makefile.am index 0e239bcd..35d9387c 100644 --- a/dbgserver/Makefile.am +++ b/dbgserver/Makefile.am @@ -62,7 +62,7 @@ man1_MANS = dbgserver-find.1 dbgserver_LDADD = $(libdw) $(libelf) $(libeu) $(libdbgserver) $(libmicrohttpd_LIBS) $(libcurl_LIBS) $(sqlite3_LIBS) $(libarchive_LIBS) -lpthread -ldl dbgserver_find_SOURCES = dbgserver-find.c -dbgserver_find_LDADD = $(libdbgserver) +dbgserver_find_LDADD = $(libeu) $(libdbgserver) noinst_LIBRARIES = libdbgserver.a noinst_LIBRARIES += libdbgserver_pic.a @@ -100,3 +100,20 @@ uninstall: uninstall-am EXTRA_DIST = libdbgserver.map dbgserver.8 dbgserver-find.1 MOSTLYCLEANFILES = $(am_libdbgserver_pic_a_OBJECTS) libdbgserver.so.$(VERSION) CLEANFILES += $(am_libdbgserver_pic_a_OBJECTS) libdbgserver.so + +# automake std-options override: arrange to pass LD_LIBRARY_PATH +installcheck-binPROGRAMS: $(bin_PROGRAMS) + bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \ + case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \ + *" $$p "* | *" $(srcdir)/$$p "*) continue;; \ + esac; \ + f=`echo "$$p" | \ + sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + for opt in --help --version; do \ + if LD_LIBRARY_PATH=$(DESTDIR)$(libdir) \ + $(DESTDIR)$(bindir)/$$f $$opt > c$${pid}_.out 2> c$${pid}_.err \ + && test -n "`cat c$${pid}_.out`" \ + && test -z "`cat c$${pid}_.err`"; then :; \ + else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \ + done; \ + done; rm -f c$${pid}_.???; exit $$bad diff --git a/dbgserver/dbgserver-client.c b/dbgserver/dbgserver-client.c index 60fe7bfa..07ff6076 100644 --- a/dbgserver/dbgserver-client.c +++ b/dbgserver/dbgserver-client.c @@ -341,10 +341,20 @@ dbgserver_query_server (const unsigned char *build_id_bytes, { /* query servers until we find the target or run out of urls to try. */ char url[PATH_MAX]; - if (filename) // starts with / - snprintf(url, PATH_MAX, "%s/buildid/%s/%s%s", server_url, build_id, type, filename); + + /* Tolerate both http://foo:999 and http://foo:999/ forms */ + char *slashbuildid; + if (strlen(server_url) > 1 && server_url[strlen(server_url)-1] == '/') + slashbuildid = "buildid"; + else + slashbuildid = "/buildid"; + + if (filename) /* must start with / */ + snprintf(url, PATH_MAX, "%s%s/%s/%s%s", server_url, + slashbuildid, build_id, type, filename); else - snprintf(url, PATH_MAX, "%s/buildid/%s/%s", server_url, build_id, type); + snprintf(url, PATH_MAX, "%s%s/%s/%s", server_url, + slashbuildid, build_id, type); curl_easy_reset(session); curl_easy_setopt(session, CURLOPT_URL, url); @@ -355,6 +365,7 @@ dbgserver_query_server (const unsigned char *build_id_bytes, curl_easy_setopt(session, CURLOPT_TIMEOUT, (long) server_timeout); curl_easy_setopt(session, CURLOPT_FILETIME, (long) 1); curl_easy_setopt(session, CURLOPT_FOLLOWLOCATION, (long) 1); + curl_easy_setopt(session, CURLOPT_FAILONERROR, (long) 1); curl_easy_setopt(session, CURLOPT_AUTOREFERER, (long) 1); curl_easy_setopt(session, CURLOPT_ACCEPT_ENCODING, ""); curl_easy_setopt(session, CURLOPT_USERAGENT, (void*) PACKAGE_STRING); @@ -362,6 +373,21 @@ dbgserver_query_server (const unsigned char *build_id_bytes, CURLcode curl_res = curl_easy_perform(session); if (curl_res != CURLE_OK) { + /* curl_easy_getinfo(session, CURLINFO_OS_ERRNO ...) would be nice if it worked. */ + switch (curl_res) /* map CURL error numbers to approximate libc errnos */ + { + case CURLE_COULDNT_RESOLVE_HOST: rc = -EHOSTUNREACH; break; // no NXDOMAIN + case CURLE_URL_MALFORMAT: rc = -EINVAL; break; + case CURLE_COULDNT_CONNECT: rc = -ECONNREFUSED; break; + case CURLE_REMOTE_ACCESS_DENIED: rc = -EACCES; break; + case CURLE_WRITE_ERROR: rc = -EIO; break; + case CURLE_OUT_OF_MEMORY: rc = -ENOMEM; break; + case CURLE_TOO_MANY_REDIRECTS: rc = -EMLINK; break; + case CURLE_SEND_ERROR: rc = -ECONNRESET; break; + case CURLE_RECV_ERROR: rc = -ECONNRESET; break; + default: rc = -ENOENT; break; + } + server_url = strtok_r(NULL, url_delim,&strtok_saveptr); continue; /* fail over to next server */ } @@ -404,8 +430,10 @@ dbgserver_query_server (const unsigned char *build_id_bytes, return fd; } -/* fell through - out of alternative servers */ - rc = -ENOENT; + /* fell through - out of alternative servers */ + /* prefer to preserve the last rc set from curl OS_ERRNO */ + if (rc == 0) + rc = -ENOENT; /* error exits */ out2: diff --git a/dbgserver/dbgserver-find.c b/dbgserver/dbgserver-find.c index caa053d4..ea31c288 100644 --- a/dbgserver/dbgserver-find.c +++ b/dbgserver/dbgserver-find.c @@ -28,46 +28,71 @@ not, see <http://www.gnu.org/licenses/>. */ #include "config.h" +#include "printversion.h" #include "dbgserver-client.h" #include <errno.h> #include <stdio.h> #include <string.h> +#include <argp.h> + + +/* Name and version of program. */ +ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; + +/* Bug report address. */ +ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; + +/* Short description of program. */ +static const char doc[] = N_("Request debuginfo-related content from dbgservers."); + +/* Strings for arguments in help texts. */ +static const char args_doc[] = N_("debuginfo BUILDID\n" + "executable BUILDID\n" + "source BUILDID /FILENAME"); + +/* Data structure to communicate with argp functions. */ +static struct argp argp = + { + NULL, NULL, args_doc, doc, NULL, NULL, NULL + }; + int main(int argc, char** argv) { - if (argc < 3 || argc > 4) + int remaining; + (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_ARGS, &remaining, NULL); + + if (remaining+1 == argc) /* at least two non-option words */ { - fprintf(stderr, "%s (%s) %s\n", argv[0], PACKAGE_NAME, PACKAGE_VERSION); - fprintf(stderr, "Usage: %s debuginfo BUILDID\n", argv[0]); - fprintf(stderr, " %s executable BUILDID\n", argv[0]); - fprintf(stderr, " %s source BUILDID /FILENAME\n", argv[0]); + argp_help (&argp, stderr, ARGP_HELP_USAGE, argv[0]); return 1; } - + int rc; char *cache_name; /* Check whether FILETYPE is valid and call the appropriate dbgserver_find_* function. If FILETYPE is "source" then ensure a FILENAME was also supplied as an argument. */ - if (strcmp(argv[1], "debuginfo") == 0) - rc = dbgserver_find_debuginfo((unsigned char *)argv[2], 0, &cache_name); - else if (strcmp(argv[1], "executable") == 0) - rc = dbgserver_find_executable((unsigned char *)argv[2], 0, &cache_name); - else if (strcmp(argv[1], "source") == 0) + if (strcmp(argv[remaining], "debuginfo") == 0) + rc = dbgserver_find_debuginfo((unsigned char *)argv[remaining+1], 0, &cache_name); + else if (strcmp(argv[remaining], "executable") == 0) + rc = dbgserver_find_executable((unsigned char *)argv[remaining+1], 0, &cache_name); + else if (strcmp(argv[remaining], "source") == 0) { - if (argc != 4 || argv[3][0] != '/') + if (remaining+2 == argc || argv[3][0] != '/') { fprintf(stderr, "If FILETYPE is \"source\" then absolute /FILENAME must be given\n"); return 1; } - rc = dbgserver_find_source((unsigned char *)argv[2], 0, argv[3], &cache_name); + rc = dbgserver_find_source((unsigned char *)argv[remaining+1], 0, + argv[remaining+2], &cache_name); } else { - fprintf(stderr, "Invalid filetype\n"); + argp_help (&argp, stderr, ARGP_HELP_USAGE, argv[0]); return 1; } diff --git a/dbgserver/dbgserver.cxx b/dbgserver/dbgserver.cxx index 4b852aee..582b0c21 100644 --- a/dbgserver/dbgserver.cxx +++ b/dbgserver/dbgserver.cxx @@ -31,7 +31,10 @@ #include "config.h" #endif +extern "C" { #include "printversion.h" +} + #include "dbgserver-client.h" #include <dwarf.h> @@ -206,7 +209,7 @@ static const char DBGSERVER_SQLITE_DDL[] = /* Name and version of program. */ -/* ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; */ +/* ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; */ // not this simple for C++ /* Bug report address. */ ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; @@ -1808,6 +1811,7 @@ main (int argc, char *argv[]) /* Parse and process arguments. */ int remaining; + argp_program_version_hook = print_version; // this works (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_ARGS, &remaining, NULL); if (remaining != argc) error (EXIT_FAILURE, 0, @@ -1934,6 +1938,10 @@ main (int argc, char *argv[]) << (d4 != NULL ? "IPv4 " : "") << (d6 != NULL ? "IPv6 " : "") << "port=" << http_port << endl; + + const char* du = getenv("DBGSERVER_URLS"); + if (du && du[0] != '\0') // set to non-empty string? + obatched(clog) << "Upstream dbgservers: " << du << endl; /* Trivial main loop! */ while (! interrupted) diff --git a/tests/run-dbgserver-find.sh b/tests/run-dbgserver-find.sh index bd3a75a6..b1549396 100755 --- a/tests/run-dbgserver-find.sh +++ b/tests/run-dbgserver-find.sh @@ -30,18 +30,30 @@ while true; do ss -atn | fgrep ":$PORT" || break done -../../dbgserver/dbgserver -vvv -d $DB -F $PWD -p $PORT & +set -x + +# We want to run dbgserver in the background. We also want to start +# it with the same check/installcheck-sensitive LD_LIBRARY_PATH stuff +# that the testrun alias sets. But: we if we just use +# testrun .../dbgserver +# it runs in a subshell, with different pid, so not helpful. +# +# So we gather the LD_LIBRARY_PATH with this cunning trick: + +ldpath=`testrun sh -c 'echo $LD_LIBRARY_PATH'` +env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../dbgserver/dbgserver -vvv -d $DB -F $PWD -p $PORT & PID=$! -trap 'kill $PID || true; rm -f $DB' 0 1 5 9 15 sleep 5 +tempfiles .dbgserver_* -export DBGSERVER_URLS=http://localhost:$PORT # XXX: no / at end; dbgserver rejects extra / +export DBGSERVER_URLS=http://localhost:$PORT/ # or without trailing / # Test whether the server is able to fetch the file from the local dbgserver. testrun ${abs_builddir}/dbgserver_build_id_find -e testfile-dbgserver.exec $EXPECT_PASS -kill $PID -rm $DB +kill -INT $PID +sleep 5 +tempfiles .dbgserver_* # Run the test again without the server running. The target file should # be found in the cache. |