Bug in 0.9.31 with __errno_location in linuxthreads.old

Peter Korsgaard jacmet at sunsite.dk
Fri Jun 18 15:14:53 UTC 2010


On Tue, May 11, 2010 at 5:19 PM, Jean-Denis Boyer
<jdboyer at media5corp.com> wrote:
>
> Here is a fix that I suggest for 0.9.31.

I ran into this issue as well, while porting some multithreaded sw to
uclibc. The patch here improves stuff, but it doesn't fix the issue :/

The problem is that access to errno doesn't seem to be thread safe.
It's easy to verify using a small test program:

#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>

#define READERS 100
#define WRITERS 100

static void *read_test(void *data)
{
	char buf[100];
	int fd, good = 0, bad = 0;

	fd = open("/dev/null", O_WRONLY);

	while (1) {
		if ((read(fd, buf, sizeof(buf)) != -1) || (errno != EBADF)) {
			int err = errno;
			fprintf(stderr, "%d: (%d/%d) got %d instead of %d\n",
				pthread_self(), bad, bad+good, err, EBADF);
			bad++;
		} else {
			good++;
		}

	}

	return 0;
}

static void *write_test(void *data)
{
	char buf[100];
	int fd, good = 0, bad = 0;

	fd = open("/dev/full", O_WRONLY);

	while (1) {
		if ((write(fd, buf, sizeof(buf)) != -1) || (errno != ENOSPC)) {
			int err = errno;
			fprintf(stderr, "%d: (%d/%d) got %d instead of %d\n",
				pthread_self(), bad, bad+good, err, ENOSPC);
			bad++;
		} else {
			good++;

		}
	}

	return 0;
}

int main(void)
{
	pthread_t id;
	int i;

	for (i=0; i<READERS; i++)
		pthread_create(&id, 0, read_test, 0);

	for (i=0; i<(WRITERS-1); i++)
		pthread_create(&id, 0, write_test, 0);

	write_test(0);

	return 0;
}

On glibc this works fine. On an unpatched uClibc 0.9.31 (and 0.9.30.3
as well) errno end up as '0' lots of times instead of the expected
EBADF/ENOSPC. With the patch below it happens less often, and I don't
see any cases where errno=0. What I do see is errno ending up as
ENOSPC when it should be EBADF and opposite.

I have tested this on ARM and x86-64. .config is the default BR config
(http://git.buildroot.net/buildroot/tree/toolchain/uClibc/uClibc-0.9.31.config).
This is with Linuxthreads.old, but a quick check with Linuxthreads
shows the same behavior.

Any ideas?

> It is in folder linuxthreads.old, but I don't know if it also applies to the "new" version.
>
> --- a/libpthread/linuxthreads.old/errno.c       2010-04-02 11:34:27.000000000 -0400
> +++ b/libpthread/linuxthreads.old/errno.c       2010-05-11 09:44:16.589502638 -0400
> @@ -22,6 +22,7 @@
>  #include "internals.h"
>  #include <stdio.h>
>
> +libpthread_hidden_proto(__errno_location)
>  int *
>  __errno_location (void)
>  {
> @@ -29,6 +30,7 @@
>   return THREAD_GETMEM (self, p_errnop);
>  }
>
> +libpthread_hidden_proto(__h_errno_location)
>  int *
>  __h_errno_location (void)
>  {
>
> The problem is shown when running the program in attachment.
> A thread cannot read the right value of errno, but the main can.
> The output of the program is:
>
> thread: Failed to connect (-1 errno=0): Operation now in progress
> main: Failed to connect (-1 errno=115): Operation now in progress
>
> Regards,
>
> Jean-Denis Boyer, Eng.
> Media5 Corporation - Mediatrix, M5T, Media5Boss
> 4229 Garlock Street, Sherbrooke (Québec), J1L 2C8, CANADA
>
> _______________________________________________
> uClibc mailing list
> uClibc at uclibc.org
> http://lists.busybox.net/mailman/listinfo/uclibc
>

-- 
Bye, Peter Korsgaard


More information about the uClibc mailing list