Improve threaded handling of errno:

- Change various incorrect direct references to errno into
  *(__errno_location()).

- In __errno_location and __h_errno_location, treat the tid==1 case
  (root thread) specially, as with __res_state().

This seems to fix a bug in threaded handling of errno on R H 9 and SuSE8.2,
and almost makes OpenOffice work again on R H 9.

MERGE TO STABLE, if it doesn't break anything.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1625 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c
index b477077..c04f15c 100644
--- a/coregrind/vg_libpthread.c
+++ b/coregrind/vg_libpthread.c
@@ -1302,7 +1302,7 @@
   if (retcode == 0) {
     return 0;
   } else {
-    errno = retcode;
+    *(__errno_location()) = retcode;
     return -1;
   }
 }
@@ -1338,7 +1338,7 @@
                            (int)(&nanosleep_interval), (int)NULL);
    }
 
-   * (__errno_location()) = EINTR;
+   *(__errno_location()) = EINTR;
    return -1;
 }
 
@@ -1589,6 +1589,8 @@
 static struct __res_state
            thread_specific_res_state[VG_N_THREADS];
 
+#undef errno
+extern int errno;
 int* __errno_location ( void )
 {
    int tid;
@@ -1599,9 +1601,13 @@
    /* 'cos I'm paranoid ... */
    if (tid < 1 || tid >= VG_N_THREADS)
       barf("__errno_location: invalid ThreadId");
+   if (tid == 1)
+      return &errno;
    return & thread_specific_errno[tid];
 }
 
+#undef h_errno
+extern int h_errno;
 int* __h_errno_location ( void )
 {
    int tid;
@@ -1612,13 +1618,14 @@
    /* 'cos I'm paranoid ... */
    if (tid < 1 || tid >= VG_N_THREADS)
       barf("__h_errno_location: invalid ThreadId");
+   if (tid == 1)
+      return &h_errno;
    return & thread_specific_h_errno[tid];
 }
 
 
 #undef _res
 extern struct __res_state _res;
-
 struct __res_state* __res_state ( void )
 {
    int tid;
@@ -1907,14 +1914,14 @@
       if (flags & VKI_O_NONBLOCK)
 	 return fd;
 
-      saved_errno = errno;
+      saved_errno = *(__errno_location());
 
       if (fd != -1)
 	 break;			/* open worked */
 
       /* If we got ENXIO and we're opening WRONLY, and it turns out
 	 to really be a FIFO, then poll waiting for open to succeed */
-      if (errno == ENXIO &&
+      if (*(__errno_location()) == ENXIO &&
 	  (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
 	  (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
 
@@ -1927,7 +1934,7 @@
 			      (int)(&nanosleep_interval), (int)NULL);
       } else {
 	 /* it was just an error */
-	 errno = saved_errno;
+	 *(__errno_location()) = saved_errno;
 	 return -1;
       }
    }
@@ -1943,7 +1950,7 @@
    */
    if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
        (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
-      errno = saved_errno;
+      *(__errno_location()) = saved_errno;
       return fd;
    }
 
@@ -1983,7 +1990,7 @@
 			   (int)(&nanosleep_interval), (int)NULL);
    }
 
-   errno = saved_errno;
+   *(__errno_location()) = saved_errno;
    return fd;
 }
 
@@ -2434,7 +2441,7 @@
    ensure_valgrind("sem_init");
    if (pshared != 0) {
       pthread_error("sem_init: unsupported pshared value");
-      errno = ENOSYS;
+      *(__errno_location()) = ENOSYS;
       return -1;
    }
    vg_sem = se_remap(sem);
@@ -2499,7 +2506,7 @@
       ret = 0; 
    } else { 
       ret = -1; 
-      errno = EAGAIN; 
+      *(__errno_location()) = EAGAIN; 
    }
    res = __pthread_mutex_unlock(&vg_sem->se_mx);
    my_assert(res == 0);