diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | libsoup/soup-socket.c | 86 |
2 files changed, 79 insertions, 20 deletions
@@ -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 */ |