Search code examples
pthreadsdetach

Bad file descriptor on pthread_detach


My pthread_detach calls fail with a "Bad file descriptor" error. The calls are in the destructor for my class and look like this -

if(pthread_detach(get_sensors) != 0)
    printf("\ndetach on get_sensors failed with error %m", errno);

if(pthread_detach(get_real_velocity) != 0) 
    printf("\ndetach on get_real_velocity failed with error %m", errno);

I have only ever dealt with this error when using sockets. What could be causing this to happen in a pthread_detach call that I should look for? Or is it likely something in the thread callback that could be causing it? Just in case, the callbacks look like this -

void* Robot::get_real_velocity_thread(void* threadid) {
    Robot* r = (Robot*)threadid;
    r->get_real_velocity_thread_i();
}

inline void Robot::get_real_velocity_thread_i() {
    while(1) {
        usleep(14500);

        sensor_packet temp = get_sensor_value(REQUESTED_VELOCITY);

        real_velocity = temp.values[0];
        if(temp.values[1] != -1)
            real_velocity += temp.values[1];
    }   //end while
}



/*Callback for get sensors thread*/
void* Robot::get_sensors_thread(void* threadid) {
    Robot* r = (Robot*)threadid;
    r->get_sensors_thread_i();
}   //END GETSENSORS_THREAD


inline void Robot::get_sensors_thread_i() {
    while(1) {

    usleep(14500);

    if(sensorsstreaming) {

        unsigned char receive;
        int read = 0;

        read = connection.PollComport(port, &receive, sizeof(unsigned char));

        if((int)receive == 19) {

            read = connection.PollComport(port, &receive, sizeof(unsigned char));

            unsigned char rest[54];

            read = connection.PollComport(port, rest, 54);

            /* ***SET SENSOR VALUES*** */
            //bump + wheel drop
            sensor_values[0] = (int)rest[1];
            sensor_values[1] = -1;
            //wall
            sensor_values[2] = (int)rest[2];
            sensor_values[3] = -1;
            ...
            ...
            lots more setting just like the two above
            }   //end if header == 19
        }   //end if sensors streaming
    }   //end while
}   //END GET_SENSORS_THREAD_I

Thank you for any help.


Solution

  • The pthread_* functions return an error code; they do not set errno. (Well, they may of course, but not in any way that is documented.)

    Your code should print the value returned by pthread_detach and print that.

    Single Unix Spec documents two return values for this function: ESRCH (no thread by that ID was found) and EINVAL (the thread is not joinable).

    Detaching threads in the destructor of an object seems silly. Firstly, if they are going to be detached eventually, why not just create them that way?

    If there is any risk that the threads can use the object that is being destroyed, they need to be stopped, not detached. I.e. you somehow indicate to the threads that they should shut down, and then wait for them to reach some safe place after which they will not touch the object any more. pthread_join is useful for this.

    Also, it is a little late to be doing that from the destructor. A destructor should only be run when the thread executing it is the only thread with a reference to that object. If threads are still using the object, then you're destroying it from under them.