File descriptor not found on pthread

Hi everybody, I was trying to make an example of a main with two pthreads, one of them registering a resource manager and a pulse_attach, and the other opening that path name and sending a pulse with MsgSendPulse but it can’t get the file descriptor correctly and thus it fails.

But when I put the code of the opening pthread on another main, compile it and run it with the first program, everything works good.

I said that the open on the second pthread fails and the error it shows is “Bad File Descriptor”, but as I said before, it works if the same code is on another program.

Do you know whats happening?? Thanx for helping! :slight_smile:

/*
*Here’s the code of the main with 2 pthreads:
*/

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <fcntl.h>
#include <pthread.h>

#include <sys/iofunc.h>
#include <sys/dispatch.h>

static resmgr_connect_funcs_t connect_func;
static resmgr_io_funcs_t io_func;
static iofunc_attr_t attr;

typedef struct
{
int argc;
char **argv;
}MainParameters;

void* PulseThread(MainParameters MainParametersObject);
void
ClientThread(void *arg);
int timer_tick(message_context_t *ctp, int code, unsigned flags, void *handle);

int main(int argc, char **argv)
{
//I can’t have two pthread_t on main, only one is valid, but with NULL both work
pthread_t *ClientThreadObjec;
//pthread_t *PulseThreadObject;

pthread_attr_t Attribute;

MainParameters *MainParametersObject;
MainParametersObject = (MainParameters *)malloc(sizeof(MainParameters));
MainParametersObject->argc = argc;
MainParametersObject->argv = argv;

/*****Only to check if argc and argv were well saved on structure
printf("\n MainParametersObject->argc = %d\n",MainParametersObject->argc);
printf("\n MainParametersObject->argv[0] = %s\n",MainParametersObject->argv[0]);
******/

pthread_attr_init( &Attribute);
pthread_attr_setdetachstate( &Attribute,PTHREAD_CREATE_DETACHED );

/*First pthread that registers the Resource Manager and which
will handle pulses
*/
pthread_create(NULL,&Attribute, &PulseThread, MainParametersObject );

/*Client pThread that open the RM and send a pulse*/
pthread_create(ClientThreadObjec,&Attribute,&ClientThread,NULL);

sleep(10);

}

void* PulseThread(MainParameters *MainParametersObject) {
resmgr_attr_t resmgr_attr;
struct sigevent event;
dispatch_t *dpp;
dispatch_context_t *ctp;
int id;

printf("\n Pulse Thread is being executed!! =) with argc =%d and argv[0] = %s\n",MainParametersObject->argc,MainParametersObject->argv[0]);

if((dpp = dispatch_create()) == NULL) {
    fprintf(stderr, "%s: Unable to allocate dispatch handle.\n",MainParametersObject->argv[0]);
    exit( EXIT_FAILURE);
}

iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_func, _RESMGR_IO_NFUNCS,
                 &io_func);
iofunc_attr_init(&attr, S_IFNAM | 0666, 0, 0);
    
memset(&resmgr_attr, 0, sizeof resmgr_attr);
resmgr_attr.nparts_max = 1;
resmgr_attr.msg_max_size = 2048;

if((id = resmgr_attach(dpp, &resmgr_attr, "/dev/sample", _FTYPE_ANY, 0,
             &connect_func, &io_func, &attr)) == -1) {
    fprintf(stderr, "%s: Unable to attach name.\n", MainParametersObject->argv[0]);
    exit( EXIT_FAILURE);
}

/* Initialize an event structure, and attach a pulse to it */
if((event.sigev_code = pulse_attach(dpp, MSG_FLAG_ALLOC_PULSE, 0, &timer_tick,
                                    NULL)) == -1) {
    fprintf(stderr, "Unable to attach timer pulse.\n");
     exit( EXIT_FAILURE);
}

/* allocate a context structure */
ctp = dispatch_context_alloc(dpp);

/* start the resource manager message loop */
while(1) {
    if((ctp = dispatch_block(ctp)) == NULL) {
        fprintf(stderr, "block error\n");
        exit( EXIT_FAILURE);
    }
    dispatch_handler(ctp);
}

}

void* ClientThread(void *arg) {
int Id;
printf("\n In Client Thread!!\n");

Id = open("/dev/sample", O_RDWR);
if (-1 == Id)
{
perror("\n Open Failed!!\n");
exit(EXIT_FAILURE);
}

printf("\n /dev/sample successfully opened!!\n");

if(MsgSendPulse(Id, getprio(0), 0,0)==-1)
{
	perror("\n Error Trying to send the pulse to /dev/sample!!\n");
	exit(EXIT_FAILURE);
}

printf("\n Pulse sent successfully!!\n");

}

int timer_tick(message_context_t *ctp, int code, unsigned flags, void *handle) {

union sigval             value = ctp->msg->pulse.value;
/*
 *  Do some useful work on every timer firing
 *  ....
 */
printf("received timer event, value %d\n", value.sival_int);
return 0;

}

/*
*Here’s the code of the sender of the pulse
*/

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <fcntl.h>
#include <pthread.h>

#include <sys/iofunc.h>
#include <sys/dispatch.h>

main()
{
int Id;
printf("\n In Client Thread!!\n");

    //Somehow this works
do
{
Id = open("/dev/sample", O_RDWR);
}while(-1==Id);

printf("\n /dev/sample successfully opened!!\n");

if(MsgSendPulse(Id, getprio(0), 0,0)==-1)
{
	perror("\n Error Trying to send the pulse to /dev/sample!!\n");
	exit(EXIT_FAILURE);
}

printf("\n Pulse sent successfully!!\n");

} :slight_smile: :slight_smile:

Adrian,

My guess is that the problem is right here:

/*First pthread that registers the Resource Manager and which 
will handle pulses 
*/ 
pthread_create(NULL,&Attribute, &PulseThread, MainParametersObject ); 

/*Client pThread that open the RM and send a pulse*/ 
pthread_create(ClientThreadObjec,&Attribute,&ClientThread,NULL); 

What I suspect happens is that the 2nd thread, the client gets spawned and reaches the open() call before the first thread (the manager) has time to actually register its name. Hence the call fails.

Try putting a sleep(1) or sleep(2) in before spawning the client thread.

Alternatively, in the client thread you have the client check once a second for 5 seconds for the manager before reporting a failure:

int success = 0;
For (i=0; i<5; i++)
{
    Id = open("/dev/sample", O_RDWR); 
    if (-1 == Id) 
    { 
        sleep (1);  // Give manager more time to start
    } 
    else
    {
        success = 1;
        break;
    }
}

if (!success)
{
    perror("\n Open Failed!!\n"); 
    exit(EXIT_FAILURE); 
}

Tim

Hi Tim, thanks for replying. I also thought about that possibility and tried with a sleep(2) between the two pthread calls in main, but the same “No such File or Directory” answer was presented, then I read your answer and tried it, but this pthread has a very bad attitude and don’t want to work well.

What I tried and partially worked was to replace the id given by the open with that given by the resmgr_attach on the MsgSendPulse, what happened was that it seemed to find /dev/sample or at least no error was found but the pulse handler on the resource manager didn’t catch the pulse :confused:.

Any help is very appreciated.

Adrián.

Eureka, I found it!! :slight_smile:…well, that was thanx to my boss Eric, thank you Eric your support is great for me.

The problem was that MsgSendPulse needs a coid in order to send the pulse and I was providing an “A unique link ID associated with this attach…”, so in order to “Create a connection to a channel” I called message_connect(), get that coid put it into the MsgSendPulse and thats it! Now It works very well.

Thank you Tim your answer came fast and I appreciate that.

Have a nice day.

Adrián.