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