Bug#266507: NPTL (0.60) quirks with pthread_create (ignores attributes)
Package: libc6
Version: 2.3.2-ds1-16
Hi,
there's a problem with the libc6 package and a 2.6.x kernel. I have attached two test programs to illustrate the problem [test_thread_attr.cc and test_thread_post.cc; compile each with -lpthread].
The programs try to create a SCHED_FIFO thread. test_thread_attr tries this by setting the attributes before creating the thread. test_thread_post does this by using setschedparam explicitly after thread creation.
test_thread_attr fails silently. It reports no error ps -C test_thread_attr -cmL shows there are no SCHED_FIFO threads created:
mango:/home/tapas# ./test_thread_attr &
[1] 2235
mango:/home/tapas# ps -C test_thread_attr -cmL
PID LWP CLS PRI TTY TIME CMD
2235 - - - pts/3 00:00:00 test_thread_att
- 2235 TS 23 - 00:00:00 -
- 2236 TS 23 - 00:00:00 -
- 2237 TS 23 - 00:00:00 -
test_thread_post succeeds:
mango:/home/tapas# ./test_thread_post &
[1] 2250
mango:/home/tapas# ps -C test_thread_post -cmL
PID LWP CLS PRI TTY TIME CMD
2250 - - - pts/3 00:00:00 test_thread_pos
- 2250 TS 23 - 00:00:00 -
- 2251 FF 50 - 00:00:00 -
- 2252 TS 23 - 00:00:00 -
The failing of test_thread_attr is not expected behaviour and was afaik a crux introduced by the libc developers to work around some missing futex[?] stuff in the kernel. see:
http://www.redhat.com/archives/phil-list/2003-January/msg00122.html
http://www.redhat.com/archives/phil-list/2003-January/msg00123.html
http://www.redhat.com/archives/phil-list/2003-July/msg00047.html
But imho this (silently breaking posix conform applications) must not happen. Either an error should be issued by pthread_create, or it should succeed. The latter is the case with NPTL 0.61.
http://www.redhat.com/archives/phil-list/2003-January/msg00122.html
basically has the one liner fix which could be applied to 0.60. Are there release plans for NPTL 0.61?
thanks,
florian schmit
--
Palimm Palimm!
http://affenbande.org/~tapas/
#include <pthread.h>
#include <unistd.h>
#include <iostream>
void *thread1_function(void*) {
while(true) {
// std::cout << "1" << std::endl;
sched_yield();
sleep(1);
}
}
void *thread2_function(void*) {
while (true) {
// std::cout << "2" << std::endl;
sched_yield();
sleep(1);
}
}
int main() {
int error;
// setup attributes for thread 1
pthread_t *thread1 = new pthread_t;
pthread_attr_t *thread1_attr = new pthread_attr_t;
error = pthread_attr_init (thread1_attr);
if (error != 0)
std::cout << "error in pthread_attr_init 1: " << strerror(error) << std::endl;
error = pthread_attr_setinheritsched(thread1_attr, PTHREAD_EXPLICIT_SCHED);
if (error != 0)
std::cout << "error in pthread_attr_setinheritsched 1: " << strerror(error) << std::endl;
error = pthread_attr_setschedpolicy(thread1_attr, SCHED_FIFO);
if (error != 0)
std::cout << "error in pthread_attr_setschedpolicy 1: " << strerror(error) << std::endl;
struct sched_param *param = new struct sched_param;
param->sched_priority = 10;
error = pthread_attr_setschedparam(thread1_attr, param);
if (error != 0)
std::cout << "error on setschedparam 1: " << strerror(error) << std::endl;
// setup attributes for thread 2
pthread_t *thread2 = new pthread_t;
pthread_attr_t *thread2_attr = new pthread_attr_t;
error = pthread_attr_init (thread2_attr);
if (error != 0)
std::cout << "error in pthread_attr_init 2: " << strerror(error) << std::endl;
// create the threads
error = pthread_create(thread1, thread1_attr, thread1_function, 0);
if (error != 0)
std::cout << "error creating thread 1: " << strerror(error) << std::endl;
error = pthread_create(thread2, thread2_attr, thread2_function, 0);
if (error != 0)
std::cout << "error creating thread 2: " << strerror(error) << std::endl;
// hang around a bit
while (true) sleep(1);
return 1;
}
#include <pthread.h>
#include <unistd.h>
#include <iostream>
void *thread1_function(void*) {
while(true) {
// std::cout << "1" << std::endl;
sched_yield();
sleep(1);
}
}
void *thread2_function(void*) {
while (true) {
// std::cout << "2" << std::endl;
sched_yield();
sleep(1);
}
}
int main() {
int error;
// setup attributes for thread 1
pthread_t *thread1 = new pthread_t;
pthread_attr_t *thread1_attr = new pthread_attr_t;
error = pthread_attr_init (thread1_attr);
if (error != 0)
std::cout << "error in pthread_attr_init 1: " << strerror(error) << std::endl;
// setup attributes for thread 2
pthread_t *thread2 = new pthread_t;
pthread_attr_t *thread2_attr = new pthread_attr_t;
error = pthread_attr_init (thread2_attr);
if (error != 0)
std::cout << "error in pthread_attr_init 2: " << strerror(error) << std::endl;
// create the threads
error = pthread_create(thread1, thread1_attr, thread1_function, 0);
if (error != 0)
std::cout << "error creating thread 1: " << strerror(error) << std::endl;
error = pthread_create(thread2, thread2_attr, thread2_function, 0);
if (error != 0)
std::cout << "error creating thread 2: " << strerror(error) << std::endl;
// do the SCHED_FIFO stuff _after_ thread creation:
struct sched_param *param = new struct sched_param;
param->sched_priority = 10;
error = pthread_setschedparam(*thread1, SCHED_FIFO, param);
if (error != 0)
std::cout << "error set_schedparam 2: " << strerror(error) << std::endl;
// hang around a bit
while (true) sleep(1);
return 1;
}
Reply to: