reorder timer initialization so that timer_create does not depend on free
[musl] / src / time / timer_create.c
index 1ac1906..2abec27 100644 (file)
@@ -61,21 +61,28 @@ int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
        struct start_args args;
        timer_t t;
        struct ksigevent ksev;
+       int timerid;
 
        if (evp) sev = *evp;
 
        switch (sev.sigev_notify) {
        case SIGEV_NONE:
        case SIGEV_SIGNAL:
-               if (!(t = calloc(1, sizeof *t)))
-                       return -1;
                ksev.sigev_value = evp ? sev.sigev_value
                        : (union sigval){.sival_ptr=t};
                ksev.sigev_signo = sev.sigev_signo;
                ksev.sigev_notify = sev.sigev_notify;
                ksev.sigev_tid = 0;
+               if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0)
+                       return -1;
+               if (!(t = calloc(1, sizeof *t))) {
+                       syscall(SYS_timer_delete, timerid);
+                       return -1;
+               }
+               t->timerid = timerid;
                break;
        case SIGEV_THREAD:
+               if (!libc.sigtimer) libc.sigtimer = sighandler;
                if (sev.sigev_notify_attributes)
                        attr = *sev.sigev_notify_attributes;
                else
@@ -95,13 +102,14 @@ int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
                ksev.sigev_signo = SIGCANCEL;
                ksev.sigev_notify = 4; /* SIGEV_THREAD_ID */
                ksev.sigev_tid = td->tid;
-               if (!libc.sigtimer) libc.sigtimer = sighandler;
+               if (syscall(SYS_timer_create, clk, &ksev, &t->timerid) < 0) {
+                       t->timerid = -1;
+                       pthread_cancel(td);
+                       return -1;
+               }
                break;
-       }
-
-       t->timerid = -1;
-       if (syscall(SYS_timer_create, clk, &ksev, &t->timerid) < 0) {
-               timer_delete(t);
+       default:
+               errno = EINVAL;
                return -1;
        }