summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--libsoup/soup-socket.c86
2 files changed, 79 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 612d4ad3..b3079f64 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
2001-08-28 Alex Graveley <alex@ximian.com>
+ * src/soup-core/soup-socket.c (soup_address_new): Perform deep
+ unix magic in order to identify if we are running in a
+ debugger. This is needed because gdb causes segfaults in child
+ processes that load shlibs due to breakpoints being left over in
+ the new unwatched process. Now, gethostbyname() loads shared libs
+ to do name resolution on many unixes, which would cause soup to be
+ hard to use and otherwise suck when run inside a debugger. So now
+ everything works perfectly both inside and outside of gdb.
+ (soup_address_new_cb): Resolve the hostname syncronously if we are
+ inside a debugger.
+
+2001-08-28 Alex Graveley <alex@ximian.com>
+
* src/soup-core/soup-context.c (soup_try_existing_connections):
Remove mega FIXME.
diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c
index 9a0bf522..040f04f8 100644
--- a/libsoup/soup-socket.c
+++ b/libsoup/soup-socket.c
@@ -41,6 +41,7 @@
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
+#include <sys/ptrace.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/utsname.h>
@@ -513,37 +514,55 @@ soup_address_new_cb (GIOChannel* iochannel,
gpointer data)
{
SoupAddressState* state = (SoupAddressState*) data;
- int rv;
- char* buf;
- int length;
struct sockaddr_in* sa_in;
GSList *cb_list, *iter;
SoupAddressNewFn cb_func;
gpointer cb_data;
- if (!(condition & G_IO_IN)) goto ERROR;
+ if (!(condition & G_IO_IN)) {
+ int ret;
- buf = &state->buffer [state->len];
- length = sizeof (state->buffer) - state->len;
+ g_source_remove (state->watch);
+ close (state->fd);
+ waitpid (state->pid, &ret, 0);
- rv = read (state->fd, buf, length);
- if (rv < 0) goto ERROR;
+ if (WIFSIGNALED (ret) || WEXITSTATUS (ret) != 1) goto ERROR;
+
+ /*
+ * Exit status of one means we are inside a debugger.
+ * Resolve the name synchronously.
+ */
+ sa_in = (struct sockaddr_in*) &state->ia.sa;
+
+ if (!soup_gethostbyname (state->ia.name, sa_in, NULL))
+ g_warning ("Problem resolving host name");
+ } else {
+ int rv;
+ char* buf;
+ int length;
- state->len += rv;
+ buf = &state->buffer [state->len];
+ length = sizeof (state->buffer) - state->len;
- /* Return true if there's more to read */
- if ((state->len - 1) != state->buffer [0]) return TRUE;
+ rv = read (state->fd, buf, length);
+ if (rv < 0) goto ERROR;
- if (state->len < 2) goto ERROR;
+ state->len += rv;
- /* Success. Copy resolved address. */
- sa_in = (struct sockaddr_in*) &state->ia.sa;
- memcpy (&sa_in->sin_addr, &state->buffer [1], (state->len - 1));
+ /* Return true if there's more to read */
+ if ((state->len - 1) != state->buffer [0]) return TRUE;
- /* Cleanup state */
- g_source_remove (state->watch);
- close (state->fd);
- waitpid (state->pid, NULL, WNOHANG);
+ if (state->len < 2) goto ERROR;
+
+ /* Success. Copy resolved address. */
+ sa_in = (struct sockaddr_in*) &state->ia.sa;
+ memcpy (&sa_in->sin_addr, &state->buffer [1], (state->len - 1));
+
+ /* Cleanup state */
+ g_source_remove (state->watch);
+ close (state->fd);
+ waitpid (state->pid, NULL, WNOHANG);
+ }
/* Get state data before realloc */
cb_list = iter = state->cb_list;
@@ -753,7 +772,34 @@ soup_address_new (const gchar* name,
case 0:
close (pipes [0]);
- /* Try to get the host by name (ie, DNS) */
+ signal (SIGCHLD, SIG_IGN);
+
+ if (ptrace (PTRACE_ATTACH, getppid (), NULL, NULL) == -1) {
+ /*
+ * Attach failed; it's probably already being
+ * debugged.
+ */
+ if (errno != EPERM)
+ g_warning ("ptrace: Unexpected error: %s",
+ strerror(errno));
+
+ _exit (1);
+ }
+
+ /*
+ * We just SIGSTOPped it; we need to CONT it now.
+ */
+ waitpid (getppid (), NULL, 0);
+
+ if (ptrace (PTRACE_DETACH, getppid (), NULL, NULL) == -1)
+ g_warning ("ptrace: Detach failed: %s",
+ strerror(errno));
+
+ kill (getppid(), SIGCONT);
+
+ /*
+ * Try to get the host by name (ie, DNS)
+ */
if (soup_gethostbyname (name, &sa, NULL)) {
guchar size = 4; /* FIX for IPv6 */