fix bogus lazy allocation in ctermid and missing malloc failure check
[musl] / src / thread / sem_open.c
index 08f98c2..9a95d25 100644 (file)
@@ -29,7 +29,7 @@ sem_t *sem_open(const char *name, int flags, ...)
        va_list ap;
        mode_t mode;
        unsigned value;
-       int fd, i, e, slot, first=1, cnt;
+       int fd, i, e, slot, first=1, cnt, cs;
        sem_t newsem;
        void *map;
        char tmp[64];
@@ -67,11 +67,13 @@ sem_t *sem_open(const char *name, int flags, ...)
 
        flags &= (O_CREAT|O_EXCL);
 
+       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+
        /* Early failure check for exclusive open; otherwise the case
         * where the semaphore already exists is expensive. */
        if (flags == (O_CREAT|O_EXCL) && access(name, F_OK) == 0) {
                errno = EEXIST;
-               return SEM_FAILED;
+               goto fail;
        }
 
        for (;;) {
@@ -80,19 +82,19 @@ sem_t *sem_open(const char *name, int flags, ...)
                if (flags != (O_CREAT|O_EXCL)) {
                        fd = open(name, FLAGS);
                        if (fd >= 0) {
-                               if ((map = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED ||
-                                   fstat(fd, &st) < 0) {
+                               if (fstat(fd, &st) < 0 ||
+                                   (map = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
                                        close(fd);
-                                       return SEM_FAILED;
+                                       goto fail;
                                }
                                close(fd);
                                break;
                        }
                        if (errno != ENOENT)
-                               return SEM_FAILED;
+                               goto fail;
                }
                if (!(flags & O_CREAT))
-                       return SEM_FAILED;
+                       goto fail;
                if (first) {
                        first = 0;
                        va_start(ap, flags);
@@ -101,7 +103,7 @@ sem_t *sem_open(const char *name, int flags, ...)
                        va_end(ap);
                        if (value > SEM_VALUE_MAX) {
                                errno = EINVAL;
-                               return SEM_FAILED;
+                               goto fail;
                        }
                        sem_init(&newsem, 1, value);
                }
@@ -112,23 +114,23 @@ sem_t *sem_open(const char *name, int flags, ...)
                fd = open(tmp, O_CREAT|O_EXCL|FLAGS, mode);
                if (fd < 0) {
                        if (errno == EEXIST) continue;
-                       return SEM_FAILED;
+                       goto fail;
                }
                if (write(fd, &newsem, sizeof newsem) != sizeof newsem || fstat(fd, &st) < 0 ||
                    (map = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
                        close(fd);
                        unlink(tmp);
-                       return SEM_FAILED;
+                       goto fail;
                }
                close(fd);
-               if (link(tmp, name) == 0) break;
-               e = errno;
+               e = link(tmp, name) ? errno : 0;
                unlink(tmp);
+               if (!e) break;
                /* Failure is only fatal when doing an exclusive open;
                 * otherwise, next iteration will try to open the
                 * existing file. */
                if (e != EEXIST || flags == (O_CREAT|O_EXCL))
-                       return SEM_FAILED;
+                       goto fail;
        }
 
        /* See if the newly mapped semaphore is already mapped. If
@@ -138,16 +140,23 @@ sem_t *sem_open(const char *name, int flags, ...)
        for (i=0; i<SEM_NSEMS_MAX && semtab[i].ino != st.st_ino; i++);
        if (i<SEM_NSEMS_MAX) {
                munmap(map, sizeof(sem_t));
-               semtab[i].refcnt++;
-               UNLOCK(lock);
-               return semtab[i].sem;
+               semtab[slot].sem = 0;
+               slot = i;
+               map = semtab[i].sem;
        }
-       semtab[slot].refcnt = 1;
+       semtab[slot].refcnt++;
        semtab[slot].sem = map;
        semtab[slot].ino = st.st_ino;
        UNLOCK(lock);
-
+       pthread_setcancelstate(cs, 0);
        return map;
+
+fail:
+       pthread_setcancelstate(cs, 0);
+       LOCK(lock);
+       semtab[slot].sem = 0;
+       UNLOCK(lock);
+       return SEM_FAILED;
 }
 
 int sem_close(sem_t *sem)