to wait until it is done with it. */
(void) __pthread_barrier_wait (¬ify_barrier);
}
- else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED)
- /* The only state we keep is the copy of the thread attributes. */
- free (data.attr);
+ else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED && data.attr != NULL)
+ {
+ /* The only state we keep is the copy of the thread attributes. */
+ pthread_attr_destroy (data.attr);
+ free (data.attr);
+ }
}
return NULL;
}
}
}
+static int
+__pthread_attr_copy (pthread_attr_t *target, const pthread_attr_t *source)
+{
+ /* Avoid overwriting *TARGET until all allocations have
+ succeeded. */
+ union
+ {
+ pthread_attr_t external;
+ struct pthread_attr internal;
+ } temp;
+
+
+ temp.external = *source;
+
+ /* Force new allocation. This function has full ownership of temp. */
+ temp.internal.cpuset = NULL;
+ temp.internal.cpusetsize = 0;
+
+ struct pthread_attr *isource = (struct pthread_attr *) source;
+
+ /* Propagate affinity mask information. */
+ if (isource->cpuset != NULL && isource->cpusetsize > 0)
+ {
+ temp.internal.cpuset = (cpu_set_t *) malloc (isource->cpusetsize);
+ if (temp.internal.cpuset == NULL)
+ return ENOMEM;
+
+ temp.internal.cpusetsize = isource->cpusetsize;
+ memcpy (temp.internal.cpuset, isource->cpuset, isource->cpusetsize);
+ }
+
+ /* Transfer ownership. *target is not assumed to have been
+ initialized. */
+ *target = temp.external;
+ return 0;
+}
/* Register notification upon message arrival to an empty message queue
MQDES. */
if (data.attr == NULL)
return -1;
- memcpy (data.attr, notification->sigev_notify_attributes,
- sizeof (pthread_attr_t));
+ int ret = __pthread_attr_copy (data.attr,
+ notification->sigev_notify_attributes);
+ if (ret != 0)
+ {
+ free (data.attr);
+ __set_errno (ret);
+ return -1;
+ }
}
/* Construct the new request. */
int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se);
/* If it failed, free the allocated memory. */
- if (__glibc_unlikely (retval != 0))
- free (data.attr);
+ if (retval != 0 && data.attr != NULL)
+ {
+ pthread_attr_destroy (data.attr);
+ free (data.attr);
+ }
return retval;
}