Skip to contentSkip to conversation

Hanging processes in T state

parisc-linux Randolph Chung 5 participants 7 messages Sep 24, 2004

lore
Share & tools
lore
#0 lore raw

pa,

Using 2.6.9-rc2 kernels, i see a lot of hanging processes when running the gdb testsuite. I checked in one fix to arch/parisc/kernel/ptrace.c that fixes most of them, but i still see some:

e.g.:

 6273 ?        T      0:00 /home/tausq/gdb/build-cvs/gdb/testsuite/gdb.mi/mi-pth
 6272 ?        T      0:00 /home/tausq/gdb/build-cvs/gdb/testsuite/gdb.mi/mi-pth
 6271 ?        T      0:00 /home/tausq/gdb/build-cvs/gdb/testsuite/gdb.mi/mi-pth

all the ones that are hanging seem to be using pthreads. anyone else see this? anyway want to do some debugging? :)

randolph

Signature · 7 lines
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/
_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
#1 lore raw

[parisc-linux] waitid doesn't work on hppa?

Quoted 6 lines · Randolph Chung

pa,

Using 2.6.9-rc2 kernels, i see a lot of hanging processes when running the gdb testsuite. I checked in one fix to arch/parisc/kernel/ptrace.c that fixes most of them, but i still see some:

Quoted 7 lines

e.g.:

 6273 ?        T      0:00 /home/tausq/gdb/build-cvs/gdb/testsuite/gdb.mi/mi-pth
 6272 ?        T      0:00 /home/tausq/gdb/build-cvs/gdb/testsuite/gdb.mi/mi-pth
 6271 ?        T      0:00 /home/tausq/gdb/build-cvs/gdb/testsuite/gdb.mi/mi-pth

all the ones that are hanging seem to be using pthreads. anyone else see this? anyway want to do some debugging? :)

Bugs in our 64-bit compat for rt_sigqueueinfo acceptance, or siginfo delivery?

I see waitid regressions in the glibc testsuite. I'm not sure if this had anything to do with these hanging processes. I haven't looked too deeply.

I constructed my usual 'out-of-build' test framework and I'm seeing:

Kernel 2.6.9-rc2-pa7, glibc 2.3.3

carlos@firin:~/fsrc/glibc-work/tests/tst-waitid$ ./ntst-waitid 
./ntst-waitid: missing SIGCHLD on stopped
./ntst-waitid: waitid WNOHANG on stopped: Not supported
carlos@firin:~/fsrc/glibc-work/tests/tst-waitid$ echo $?
1

Kernel 2.6.9-rc2-pa7, glibc 2.3.2.ds1-13

carlos@firin:~/fsrc/glibc-work/tests/tst-waitid$ ./tst-waitid 
./tst-waitid: missing SIGCHLD on stopped
./tst-waitid: waitid WSTOPPED|WNOHANG on stopped signal 0
carlos@firin:~/fsrc/glibc-work/tests/tst-waitid$ echo $?
1

Test attached if you wish to work on it? :)

Cheers,
Carlos.

---
/* Tests for waitid.
Copyright (C) 2004 Free Software Foundation, Inc. This file is part of the GNU C Library.

The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */

#include <errno.h>
#include <error.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>

#define TIMEOUT 15

static void
test_child (void)
{
/* Wait a second to be sure the parent set his variables before we
produce a SIGCHLD. */
sleep (5);

/* First thing, we stop ourselves. */
raise (SIGSTOP);

/* Hey, we got continued! */
while (1)

    pause ();
}

#ifndef WEXITED

# define WEXITED	0
# define WCONTINUED	0
# define WSTOPPED	WUNTRACED
#endif

static sig_atomic_t expecting_sigchld, spurious_sigchld; #ifdef SA_SIGINFO
static siginfo_t sigchld_info;

static void
sigchld (int signo, siginfo_t *info, void *ctx)
{
if (signo != SIGCHLD)

    {
      error (0, 0, "SIGCHLD handler got signal %d instead!", signo);
      _exit (EXIT_FAILURE);
    }

if (! expecting_sigchld)

    {
      spurious_sigchld = 1;
      error (0, 0,
	     "spurious SIGCHLD: signo %d code %d status %d pid %d\n",
	     info->si_signo, info->si_code, info->si_status, info->si_pid);
    }
  else
    {
      sigchld_info = *info;
      expecting_sigchld = 0;
    }
}

static void
check_sigchld (const char *phase, int *ok, int code, int status, pid_t pid) {
if (expecting_sigchld)

    {
      error (0, 0, "missing SIGCHLD on %s", phase);
      *ok = EXIT_FAILURE;
      expecting_sigchld = 0;
      return;
    }

if (sigchld_info.si_signo != SIGCHLD)

    {
      error (0, 0, "SIGCHLD for %s signal %d", phase, sigchld_info.si_signo);
      *ok = EXIT_FAILURE;
    }
  if (sigchld_info.si_code != code)
    {
      error (0, 0, "SIGCHLD for %s code %d", phase, sigchld_info.si_code);
      *ok = EXIT_FAILURE;
    }
  if (sigchld_info.si_status != status)
    {
      error (0, 0, "SIGCHLD for %s status %d", phase, sigchld_info.si_status);
      *ok = EXIT_FAILURE;
    }
  if (sigchld_info.si_pid != pid)
    {
      error (0, 0, "SIGCHLD for %s pid %d", phase, sigchld_info.si_pid);
      *ok = EXIT_FAILURE;
    }
}
# define CHECK_SIGCHLD(phase, code_check, status_check) \
  check_sigchld ((phase), &status, (code_check), (status_check), pid)
#else
# define CHECK_SIGCHLD(phase, code, status) ((void) 0)
#endif

int
main (int argc, char *argv[])
{
#ifdef SA_SIGINFO
struct sigaction sa;
sa.sa_flags = SA_SIGINFO|SA_RESTART;
sa.sa_sigaction = &sigchld;
if (sigemptyset (&sa.sa_mask) < 0 || sigaction (SIGCHLD, &sa, NULL) < 0)

    {
      error (0, errno, "setting SIGCHLD handler");
      return EXIT_FAILURE;
    }

#endif

  expecting_sigchld = 1;

  pid_t pid = fork ();
  if (pid < 0)
    {
      error (0, errno, "fork");
      return EXIT_FAILURE;
    }
  else if (pid == 0)
    {
      test_child ();
      _exit (127);
    }

int status = EXIT_SUCCESS;

#define RETURN(ok) \
    do { if (status == EXIT_SUCCESS) status = (ok); goto out; } while (0)

/* Give the child a chance to stop. */
sleep (3);

  CHECK_SIGCHLD ("stopped", CLD_STOPPED, SIGSTOP);

/* Now try a wait that should not succeed. */ siginfo_t info;
info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
int fail = waitid (P_PID, pid, &info, WEXITED|WCONTINUED|WNOHANG); switch (fail)

    {
    default:
      error (0, 0, "waitid returned bogus value %d\n", fail);
      RETURN (EXIT_FAILURE);
    case -1:
      error (0, errno, "waitid WNOHANG on stopped");
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
    case 0:
      if (info.si_signo == 0)
	break;
      if (info.si_signo == SIGCHLD)
	error (0, 0, "waitid WNOHANG on stopped status %d\n", info.si_status);
      else
	error (0, 0, "waitid WNOHANG on stopped signal %d\n", info.si_signo);
      RETURN (EXIT_FAILURE);
    }

/* Next the wait that should succeed right away. */
info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
info.si_pid = -1;
info.si_status = -1;
fail = waitid (P_PID, pid, &info, WSTOPPED|WNOHANG); switch (fail)

    {
    default:
      error (0, 0, "waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail);
      RETURN (EXIT_FAILURE);
    case -1:
      error (0, errno, "waitid WSTOPPED|WNOHANG on stopped");
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
    case 0:
      if (info.si_signo != SIGCHLD)
	{
	  error (0, 0, "waitid WSTOPPED|WNOHANG on stopped signal %d\n",
		 info.si_signo);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_code != CLD_STOPPED)
	{
	  error (0, 0, "waitid WSTOPPED|WNOHANG on stopped code %d\n",
		 info.si_code);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_status != SIGSTOP)
	{
	  error (0, 0, "waitid WSTOPPED|WNOHANG on stopped status %d\n",
		 info.si_status);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_pid != pid)
	{
	  error (0, 0, "waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n",
		 info.si_pid, pid);
	  RETURN (EXIT_FAILURE);
	}
    }
  expecting_sigchld = WCONTINUED != 0;

  if (kill (pid, SIGCONT) != 0)
    {
      error (0, errno, "kill (%d, SIGCONT)", pid);
      RETURN (EXIT_FAILURE);
    }

/* Wait for the child to have continued. */
sleep (2);

#if WCONTINUED != 0
if (expecting_sigchld)

    {
      error (0, 0, "no SIGCHLD seen for SIGCONT (optional)");
      expecting_sigchld = 0;
    }
  else
    CHECK_SIGCHLD ("continued", CLD_CONTINUED, SIGCONT);

info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
info.si_pid = -1;
info.si_status = -1;
fail = waitid (P_PID, pid, &info, WCONTINUED|WNOWAIT); switch (fail)

    {
    default:
      error (0, 0,
	     "waitid WCONTINUED|WNOWAIT returned bogus value %d\n", fail);
      RETURN (EXIT_FAILURE);
    case -1:
      error (0, errno, "waitid WCONTINUED|WNOWAIT on continued");
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
    case 0:
      if (info.si_signo != SIGCHLD)
	{
	  error (0, 0, "waitid WCONTINUED|WNOWAIT on continued signal %d\n",
		 info.si_signo);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_code != CLD_CONTINUED)
	{
	  error (0, 0, "waitid WCONTINUED|WNOWAIT on continued code %d\n",
		 info.si_code);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_status != SIGCONT)
	{
	  error (0, 0, "waitid WCONTINUED|WNOWAIT on continued status %d\n",
		 info.si_status);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_pid != pid)
	{
	  error (0, 0, "waitid WCONTINUED|WNOWAIT on continued pid %d != %d\n",
		 info.si_pid, pid);
	  RETURN (EXIT_FAILURE);
	}
    }

/* That should leave the CLD_CONTINUED state waiting to be seen again. */
info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
info.si_pid = -1;
info.si_status = -1;
fail = waitid (P_PID, pid, &info, WCONTINUED);
switch (fail)

    {
    default:
      error (0, 0, "waitid WCONTINUED returned bogus value %d\n", fail);
      RETURN (EXIT_FAILURE);
    case -1:
      error (0, errno, "waitid WCONTINUED on continued");
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
    case 0:
      if (info.si_signo != SIGCHLD)
	{
	  error (0, 0, "waitid WCONTINUED on continued signal %d\n",
		 info.si_signo);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_code != CLD_CONTINUED)
	{
	  error (0, 0, "waitid WCONTINUED on continued code %d\n",
		 info.si_code);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_status != SIGCONT)
	{
	  error (0, 0, "waitid WCONTINUED on continued status %d\n",
		 info.si_status);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_pid != pid)
	{
	  error (0, 0, "waitid WCONTINUED on continued pid %d != %d\n",
		 info.si_pid, pid);
	  RETURN (EXIT_FAILURE);
	}
    }

/* Now try a wait that should not succeed. */
info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
fail = waitid (P_PID, pid, &info, WCONTINUED|WNOHANG); switch (fail)

    {
    default:
      error (0, 0, "waitid returned bogus value %d\n", fail);
      RETURN (EXIT_FAILURE);
    case -1:
      error (0, errno, "waitid WCONTINUED|WNOHANG on waited continued");
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
    case 0:
      if (info.si_signo == 0)
	break;
      if (info.si_signo == SIGCHLD)
	error (0, 0,
	       "waitid WCONTINUED|WNOHANG on waited continued status %d\n",
	       info.si_status);
      else
	error (0, 0,
	       "waitid WCONTINUED|WNOHANG on waited continued signal %d\n",
	       info.si_signo);
      RETURN (EXIT_FAILURE);
    }

#endif

  expecting_sigchld = 1;

  /* Die, child, die!  */
  if (kill (pid, SIGKILL) != 0)
    {
      error (0, errno, "kill (%d, SIGKILL)", pid);
      RETURN (EXIT_FAILURE);
    }

#ifdef WNOWAIT
info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
info.si_pid = -1;
info.si_status = -1;
fail = waitid (P_PID, pid, &info, WEXITED|WNOWAIT); switch (fail)

    {
    default:
      error (0, 0, "waitid WNOWAIT returned bogus value %d\n", fail);
      RETURN (EXIT_FAILURE);
    case -1:
      error (0, errno, "waitid WNOWAIT on killed");
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
    case 0:
      if (info.si_signo != SIGCHLD)
	{
	  error (0, 0, "waitid WNOWAIT on killed signal %d\n",
		 info.si_signo);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_code != CLD_KILLED)
	{
	  error (0, 0, "waitid WNOWAIT on killed code %d\n",
		 info.si_code);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_status != SIGKILL)
	{
	  error (0, 0, "waitid WNOWAIT on killed status %d\n",
		 info.si_status);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_pid != pid)
	{
	  error (0, 0, "waitid WNOWAIT on killed pid %d != %d\n",
		 info.si_pid, pid);
	  RETURN (EXIT_FAILURE);
	}
    }

#else
/* Allow enough time to be sure the child died; we didn't synchronize. */ sleep (2);
#endif

  CHECK_SIGCHLD ("killed", CLD_KILLED, SIGKILL);

info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
info.si_pid = -1;
info.si_status = -1;
fail = waitid (P_PID, pid, &info, WEXITED|WNOHANG); switch (fail)

    {
    default:
      error (0, 0, "waitid WNOHANG returned bogus value %d\n", fail);
      RETURN (EXIT_FAILURE);
    case -1:
      error (0, errno, "waitid WNOHANG on killed");
      RETURN (EXIT_FAILURE);
    case 0:
      if (info.si_signo != SIGCHLD)
	{
	  error (0, 0, "waitid WNOHANG on killed signal %d\n",
		 info.si_signo);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_code != CLD_KILLED)
	{
	  error (0, 0, "waitid WNOHANG on killed code %d\n",
		 info.si_code);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_status != SIGKILL)
	{
	  error (0, 0, "waitid WNOHANG on killed status %d\n",
		 info.si_status);
	  RETURN (EXIT_FAILURE);
	}
      if (info.si_pid != pid)
	{
	  error (0, 0, "waitid WNOHANG on killed pid %d != %d\n",
		 info.si_pid, pid);
	  RETURN (EXIT_FAILURE);
	}
    }

fail = waitid (P_PID, pid, &info, WEXITED);
if (fail == -1)

    {
      if (errno != ECHILD)
	{
	  error (0, errno, "waitid WEXITED on killed");
	  RETURN (EXIT_FAILURE);
	}
    }
  else
    {
      error (0, 0, "waitid WEXITED returned bogus value %d\n", fail);
      RETURN (EXIT_FAILURE);
    }

#undef RETURN
out:
if (spurious_sigchld)

    status = EXIT_FAILURE;

signal (SIGCHLD, SIG_IGN);
kill (pid, SIGKILL); /* Make sure it's dead if we bailed early. */
return status;
}

_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux

#2 lore raw

Re: [parisc-linux] waitid doesn't work on hppa?

Quoted 3 lines

I see waitid regressions in the glibc testsuite. I'm not sure if this had anything to do with these hanging processes. I haven't looked too deeply.

This is probably the cause of the expect hangs. For some reason tcl8.3 works better than 8.4.

Dave

Signature · 6 lines
J. David Anglin                                  [email protected]
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)
_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
#3 lore raw

Re: [parisc-linux] waitid doesn't work on hppa?

In reference to a message from John David Anglin, dated Sep 24:

Quoted 6 lines
Quoted 3 lines

I see waitid regressions in the glibc testsuite. I'm not sure if this had anything to do with these hanging processes. I haven't looked too deeply.

This is probably the cause of the expect hangs. For some reason tcl8.3 works better than 8.4.

i don't think expect/tcl uses waitid (not waitpid....)

randolph

Signature · 7 lines
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/
_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
#4 lore raw

Re: [parisc-linux] waitid doesn't work on hppa?

In reply to Carlos O'Donell
Quoted 3 lines · Carlos O'Donell

I see waitid regressions in the glibc testsuite. I'm not sure if this had anything to do with these hanging processes. I haven't looked too deeply.

i know we tried a 20040916 glibc snapshot at Gentoo but had to abandon it because of so many problems ...

one of them is what you describe, processes running just fine but hanging just before exit ... but we saw that on amd64 ...
in other words, these waitpid problems are probably not arch related :)

here's what i noticed in an amd64 chroot:
- 20040808 glibc snapshot works great
- install 20040916 glibc snapshot, things work fine
- rebuild bash against 20040916 ... suddenly all child processes of the new bash shells hang after they've completed normal operations ... note that bash is the *only* app that's been recompiled against the new glibc
- install 20040808 glibc, bug persists; rebuild bash, things works fine again ...
-mike
_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux

#5 lore raw

Re: [parisc-linux] waitid doesn't work on hppa?

In reply to Carlos O'Donell
Quoted 3 lines · Carlos O'Donell

I see waitid regressions in the glibc testsuite. I'm not sure if this had anything to do with these hanging processes. I haven't looked too deeply.

Possibly it's because we haven't hooked up sys_waitid yet?

Signature · 10 lines
"Next the statesmen will invent cheap lies, putting the blame upon 
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince 
himself that the war is just, and will thank God for the better sleep 
he enjoys after this process of grotesque self-deception." -- Mark Twain
_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
#6 lore raw

[parisc-linux] waitid is badly emulated with waitpid (cannot reap child and a couple of other things)

Quoted 6 lines · Matthew Wilcox
Quoted 3 lines · Carlos O'Donell

I see waitid regressions in the glibc testsuite. I'm not sure if this had anything to do with these hanging processes. I haven't looked too deeply.

Possibly it's because we haven't hooked up sys_waitid yet?

It's supposed to fall back and emulate sys_waitid with a couple other syscalls. Who knows if this emulation is working correctly.

The emualted waitid() cannot handle all the proper modes apparently, which means things like reaping children is not possible since waitpid() is used.

I think we definately want to have sys_waitid() connected soon.

c.
_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux