Unix Programming - message queues and pthreads

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > February 2004 > message queues and pthreads





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author message queues and pthreads
Reid Nichol

2004-02-22, 6:34 am

Hello,
this is my first time programming with pthreads and message queues.
I am using sys/msg.h for the message queues.

My client program is able to connect and disconnect from the server
no problem. But, when I add in a message queue the server just hangs.

The server sets up the receiving thread, pops off another for the
sending and then uses recv (blocking) to wait for more info from the client.

But, when I send the quit signal from the client, the server doesn't
even acknowledge that the data has been sent. The server just sits their.

It almost seems as though the send thread is blocking the recieve thread.

Here is the relevent code:

SERVER:
RECIEVE THREAD
/* and we pop off a thread for the back connect */
fprintf(stderr, "pop off the thread\n");
if (pthread_create(&users_logged_in[number_users_logged_in -
1].send_tid, &pthread_attr, launch_cas_s, (void*)&passed) != 0) {
fprintf(stderr, "can't get send thread going\n");
if (send(csocket, (const void*)"0", (size_t)1, NULL) <= 0) {
fprintf(stderr, "problem send err code\n");
}
close(csocket);
number_users_logged_in--;
tmp = (struct Users *)realloc((void*)users_logged_in,
number_users_logged_in*sizeof(struct Users));
if (tmp == NULL) {
fprintf(stderr, "horrible things are happening\n");
}
users_logged_in = tmp;

pthread_exit(NULL);
}

fprintf(stderr, "successful login\n");
if (send(csocket, (const void*)"1", (size_t)1, NULL) <= 0) {
fprintf(stderr, "problem sending success code\n");
close(csocket);
pthread_exit(NULL);
}

/* here is the game loop */
fprintf(stderr, "everything went as planned - starting loop\n");
do {
/* this is where is "hangs" here */
fprintf(stderr, "WAITING FOR DATA\n");

ret = recv(csocket, (void*)r_c, sizeof(char), NULL);
fprintf(stderr, "got something\n");
if (ret < 0) {
fprintf(stderr, "error occured\n");
}
fprintf(stderr, "ret %d == got %s\n", ret, r_c);
if ((ret = strncmp(r_c, "-", 1)) == 0) {
keep_going = 1;
} else {
/* this is where everything happens */
r_i = atoi(r_c);
fprintf(stderr, "everything happens here, got %d\n", r_i);
}
} while (keep_going == 0);

SEND THREAD
/* we now init the message queue */
fprintf(stderr, "setting up the msg queue\n");
i = 0;
while (i < number_users_logged_in) {
if (users_logged_in[i].user_id == passed.id) {
break;
}
i++;
}
users_logged_in[i].send_msg_id =
msgget((key_t)users_logged_in[i].user_id, msgflg);

msg_queue_id = users_logged_in[i].send_msg_id;
if (msg_queue_id < 0) {
fprintf(stderr, "problems\n");
} else {
fprintf(stderr, "no problems\n");
}

fprintf(stderr, "starting waiting on the queue\n");
/* this is where is hangs here */
while (msgrcv(msg_queue_id, (void*)&msgp, (size_t)msgp_max, 0, 0) > 0) {
fprintf(stderr, "got msg\n");
if (strncmp(msgp.mtext, "-", 1) == 0) {
fprintf(stderr, "got breaking signal\n");
break;
}
}
msgctl(msg_queue_id, IPC_RMID, (struct msqid_ds *)NULL);

Nick Landsberg

2004-02-22, 6:34 am



Reid Nichol wrote:

> Hello,
> this is my first time programming with pthreads and message queues. I=

=20
> am using sys/msg.h for the message queues.
>=20
> My client program is able to connect and disconnect from the server n=

o=20
> problem. But, when I add in a message queue the server just hangs.
>=20
> The server sets up the receiving thread, pops off another for the=20
> sending and then uses recv (blocking) to wait for more info from the=20
> client.
>=20
> But, when I send the quit signal from the client, the server doesn't =


> even acknowledge that the data has been sent. The server just sits the=

ir.
>=20
> It almost seems as though the send thread is blocking the recieve thr=

ead.
>=20
> Here is the relevent code:
>=20
> SERVER:
> RECIEVE THREAD
> /* and we pop off a thread for the back connect */
> fprintf(stderr, "pop off the thread\n");
> if (pthread_create(&users_logged_in[number_users_logged_in -=20
> 1].send_tid, &pthread_attr, launch_cas_s, (void*)&passed) !=3D 0) {
> fprintf(stderr, "can't get send thread going\n");
> if (send(csocket, (const void*)"0", (size_t)1, NULL) <=3D 0) {
> fprintf(stderr, "problem send err code\n");
> }
> close(csocket);
> number_users_logged_in--;
> tmp =3D (struct Users *)realloc((void*)users_logged_in,=20
> number_users_logged_in*sizeof(struct Users));
> if (tmp =3D=3D NULL) {
> fprintf(stderr, "horrible things are happening\n");
> }
> users_logged_in =3D tmp;
>=20
> pthread_exit(NULL);
> }
>=20
> fprintf(stderr, "successful login\n");
> if (send(csocket, (const void*)"1", (size_t)1, NULL) <=3D 0) {
> fprintf(stderr, "problem sending success code\n");
> close(csocket);
> pthread_exit(NULL);
> }
>=20
> /* here is the game loop */
> fprintf(stderr, "everything went as planned - starting loop\n");
> do {
> /* this is where is "hangs" here */
> fprintf(stderr, "WAITING FOR DATA\n");
>=20
> ret =3D recv(csocket, (void*)r_c, sizeof(char), NULL);

^^^^
My man page for recv() specifies that the flags parameter
(which you pass as NULL) is constructed by or-ing three
flags, i.e.
MSG_OOB process out-of-band data
MSG_PEEK peek at incoming message
MSG_WAITALL wait for full request or error

presumably, none of these are defined in the header
file as NULL.

HTH

> fprintf(stderr, "got something\n");
> if (ret < 0) {
> fprintf(stderr, "error occured\n");
> }
> fprintf(stderr, "ret %d =3D=3D got %s\n", ret, r_c);
> if ((ret =3D strncmp(r_c, "-", 1)) =3D=3D 0) {
> keep_going =3D 1;
> } else {
> /* this is where everything happens */
> r_i =3D atoi(r_c);
> fprintf(stderr, "everything happens here, got %d\n", r_i);
> }
> } while (keep_going =3D=3D 0);
>=20
> SEND THREAD
> /* we now init the message queue */
> fprintf(stderr, "setting up the msg queue\n");
> i =3D 0;
> while (i < number_users_logged_in) {
> if (users_logged_in[i].user_id =3D=3D passed.id) {
> break;
> }
> i++;
> }
> users_logged_in[i].send_msg_id =3D=20
> msgget((key_t)users_logged_in[i].user_id, msgflg);
>=20
> msg_queue_id =3D users_logged_in[i].send_msg_id;
> if (msg_queue_id < 0) {
> fprintf(stderr, "problems\n");
> } else {
> fprintf(stderr, "no problems\n");
> }
>=20
> fprintf(stderr, "starting waiting on the queue\n");
> /* this is where is hangs here */
> while (msgrcv(msg_queue_id, (void*)&msgp, (size_t)msgp_max, 0, 0) > 0) =

{
> fprintf(stderr, "got msg\n");
> if (strncmp(msgp.mtext, "-", 1) =3D=3D 0) {
> fprintf(stderr, "got breaking signal\n");
> break;
> }
> }
> msgctl(msg_queue_id, IPC_RMID, (struct msqid_ds *)NULL);
>=20


--=20
=D1
"It is impossible to make anything foolproof because fools are so=20
ingenious" - A. Bloch

Reid Nichol

2004-02-22, 7:34 am

>
> ^^^^
> My man page for recv() specifies that the flags parameter
> (which you pass as NULL) is constructed by or-ing three
> flags, i.e.
> MSG_OOB process out-of-band data
> MSG_PEEK peek at incoming message
> MSG_WAITALL wait for full request or error
>
> presumably, none of these are defined in the header
> file as NULL.
>
> HTH

Same as mine. But, when I looked at online tutorials they did use NULL.
I did try MSG_WAITALL but the result is the same behavior.

Nick Landsberg

2004-02-22, 8:34 am



Reid Nichol wrote:

>=20
> Same as mine. But, when I looked at online tutorials they did use NULL=

=2E=20
> I did try MSG_WAITALL but the result is the same behavior.
>=20


OK ... the call which seems to hang is:

ret =3D recv(csocket, (void*)r_c, sizeof(char), NULL);

What's the r_c declared as?
(you didn't post your declarations, BTW).

As I interpret this, you are trying to read a single
character from the socket. r_c should be a pointer
to a character, or a pointer to a character within an
array, but a pointer nontheless.

If r_c is declared as just a char (not a char *)
and uninitialized, casting
it to a pointer may have the pointer pointing off into
never-never land.

--=20
=D1
"It is impossible to make anything foolproof because fools are so=20
ingenious" - A. Bloch

Reid Nichol

2004-02-22, 9:34 am

>
> OK ... the call which seems to hang is:
>
> ret = recv(csocket, (void*)r_c, sizeof(char), NULL);

This works fine when there isn't any message queue in the code but
freezes when there is one. It's like msgrcv is blocking the entire
program instead of just the one thread.

>
> What's the r_c declared as?
> (you didn't post your declarations, BTW).

char r_c[2];

The code compiles clean so I think that we can assume that they are of
the right type, unless I'm mistake of course. I haven't done any
serious programming in some time.

Nick Landsberg

2004-02-22, 9:34 am



Reid Nichol wrote:

>=20
> This works fine when there isn't any message queue in the code but=20
> freezes when there is one. It's like msgrcv is blocking the entire=20
> program instead of just the one thread.
>=20
>=20
> char r_c[2];
>=20
> The code compiles clean so I think that we can assume that they are of =


> the right type, unless I'm mistake of course. I haven't done any=20
> serious programming in some time.
>=20


It may compile clean, but the cast to (void *) shut the compiler
up about the mismatch.

What you are saying to the compiler is that you want to take
the >value< stored in r_c and use that >value< as a void
pointer. What you want is an address at which to store the
single character you are reading into it. I guess you were
unlucky in that this did not cause a segmentation violation.

Replace it with

ret =3D recv(csocket, (void*)&r_c, sizeof(char), FLAGS);

(either NULL or one the other flags) and see if that helps.


--=20
=D1
"It is impossible to make anything foolproof because fools are so=20
ingenious" - A. Bloch

Reid Nichol

2004-02-22, 12:33 pm

Switched to UNIX domain sockets. Works now.

Daniel Rakel

2004-02-23, 1:34 am

Nick Landsberg wrote:

>
> It may compile clean, but the cast to (void *) shut the compiler
> up about the mismatch.
>
> What you are saying to the compiler is that you want to take
> the >value< stored in r_c and use that >value< as a void
> pointer. What you want is an address at which to store the
> single character you are reading into it. I guess you were
> unlucky in that this did not cause a segmentation violation.
>
> Replace it with
>
> ret = recv(csocket, (void*)&r_c, sizeof(char), FLAGS);


Your replacement is wrong. You pass the address of the array. But using
the array name r_c will pass a pointer to the first element of the array.
Maybe (if the application protocol requires it) the OP needs to adjust the
size parameter too.

ret = recv(csocket, r_c, sizeof r_c, FLAGS);

Regards,
Daniel
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com