[summary: Get rid of libc alias __GI___errno_location]

It seems with Linuxthreads.old (yet to confirm NPTL) errno is not thread
safe.

A simple pthread linked test program (at the bottom) which makes a
failing syscall e.g. open("/not-exist") fails to observe the right errno
in the thread (main is OK)

Conceptually uClibc defines weak __errno_location() while libpthread
defines astrong variant. This arrangement shd work when using -pthread
links. The spoil sport is __GI___errno_location, intended to bypass PLT
for intra-libc callers. It gets called even in case of LT.old links
given the syscall wrappers in  libpthread (LT.old). e.g.

open [ in libpthread ]
  pthreadsetcanceltype()
   __libc_open()
      __GI__open()
           ...
-           __GI___errno_location    [ existing ]
+           __errno_location         [ intended ]
   ....
  pthreadsetcanceltype()

So the solution is to get rid of GI alias for errno_location
altogether.

I tested this on master for ARC as well as an ARMv7 buildroot LT.old
build (daily snapshot of uClibc) and fix works on both.

-------- before ------->8----------

[Main thread] Initial errno = 99
errno @b6f6c338 = 2 (OK)

[Child Thread] Initial errno = 0
errno @be1ffee8 = 0 (BROKEN)
Errno in main after child 4

------- after ----->8------------------

[Main thread] Initial errno = 99
errno @b6f9a338 = 2 (OK)

[Child Thread] Initial errno = 0
errno @be1ffee8 = 2 (OK)
Errno in main after child 4

============Test case ===================
/* $CROSS-gcc -o errno-arc -lpthread */

void *th(void *str)
{
        int fd;
        printf("\n[%s] Initial errno = %d\n", (char *)str, errno);

        fd = open("/nothing", O_RDONLY);
        if (fd >= 0) {
                close(fd);
                //printf("success\n");
        } else
                printf("errno @%x = %d (%s)\n", &errno, errno, errno ?  "OK" : 
"BROKEN");

        errno = 66;

        return NULL;
}

int main(void)
{
        pthread_t t;
        void *r;
        int err;

        errno = 99;
        th("Main thread");

        err = pthread_create(&t, NULL, th, "Child Thread");
        if (err) {
                fprintf(stderr, "could not spawn thread: %s\n", strerror(err));
                return 1;
        }
        pthread_join(t, &r);

        printf("Errno in main after child %d\n", errno);
        return 0;
}

Cc: Christian Ruppert <[email protected]>
CC: Francois Bedard <[email protected]>
Cc: Joern Rennecke  <[email protected]>
Cc: Jeremy Bennett <[email protected]>
Signed-off-by: Vineet Gupta <[email protected]>
---
 libc/misc/internals/__errno_location.c | 1 -
 libc/sysdeps/linux/common/bits/errno.h | 3 ---
 2 files changed, 4 deletions(-)

diff --git a/libc/misc/internals/__errno_location.c 
b/libc/misc/internals/__errno_location.c
index be7a9093efa3..9bbc2d779653 100644
--- a/libc/misc/internals/__errno_location.c
+++ b/libc/misc/internals/__errno_location.c
@@ -16,4 +16,3 @@ int *__errno_location(void)
 {
     return &errno;
 }
-libc_hidden_weak(__errno_location)
diff --git a/libc/sysdeps/linux/common/bits/errno.h 
b/libc/sysdeps/linux/common/bits/errno.h
index 777338fb1e0a..611b8359001a 100644
--- a/libc/sysdeps/linux/common/bits/errno.h
+++ b/libc/sysdeps/linux/common/bits/errno.h
@@ -43,11 +43,8 @@
 /* Function to get address of global `errno' variable.  */
 extern int *__errno_location (void) __THROW __attribute__ ((__const__));
 #  ifdef _LIBC
-#   if !defined(__UCLIBC_HAS_TLS__) && !defined(__UCLIBC_HAS_THREADS__)
 extern int weak_const_function *__errno_location(void);
-#   endif
 #  endif
-libc_hidden_proto(__errno_location)
 
 #  ifdef __UCLIBC_HAS_THREADS__
 /* When using threads, errno is a per-thread value.  */
-- 
1.8.3.2

_______________________________________________
uClibc mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to