chansrv: fix for deadlock

This commit is contained in:
Jay Sorg 2013-09-23 12:16:52 -07:00
parent db71bc5d8b
commit dfd78c722b
3 changed files with 98 additions and 2 deletions

View File

@ -291,6 +291,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s)
size = (int)(out_s->end - out_s->data);
total = 0;
self->in_write = 1;
while (total < size)
{
sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0);
@ -308,6 +309,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s)
{
/* term */
self->status = TRANS_STATUS_DOWN;
self->in_write = 0;
return 1;
}
}
@ -317,6 +319,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s)
{
/* error */
self->status = TRANS_STATUS_DOWN;
self->in_write = 0;
return 1;
}
}
@ -324,6 +327,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s)
{
/* error */
self->status = TRANS_STATUS_DOWN;
self->in_write = 0;
return 1;
}
else
@ -331,6 +335,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s)
total = total + sent;
}
}
self->in_write = 0;
return 0;
}
@ -342,6 +347,84 @@ trans_force_write(struct trans *self)
return trans_force_write_s(self, self->out_s);
}
/*****************************************************************************/
int APP_CC
trans_write_check(struct trans* self, int timeout)
{
int size;
int total;
int sent;
int error;
tbus robjs[1];
tbus wobjs[1];
struct stream *out_s;
if (self->status != TRANS_STATUS_UP)
{
return 1;
}
out_s = self->out_s;
size = (int)(out_s->end - out_s->data);
total = 0;
self->in_write = 1;
while (total < size)
{
robjs[0] = self->sck;
wobjs[0] = self->sck;
error = g_obj_wait(robjs, 1, wobjs, 1, timeout);
if (error != 0)
{
/* error */
self->status = TRANS_STATUS_DOWN;
self->in_write = 0;
return 1;
}
if (!g_tcp_can_send(self->sck, 0))
{
trans_check_wait_objs(self);
continue;
}
sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0);
if (sent == -1)
{
if (g_tcp_last_error_would_block(self->sck))
{
if (!g_tcp_can_send(self->sck, 10))
{
/* check for term here */
}
}
else
{
/* error */
self->status = TRANS_STATUS_DOWN;
self->in_write = 0;
return 1;
}
}
else if (sent == 0)
{
/* error */
self->status = TRANS_STATUS_DOWN;
self->in_write = 0;
return 1;
}
else
{
total = total + sent;
}
}
self->in_write = 0;
return 0;
}
/*****************************************************************************/
int APP_CC
trans_connect(struct trans *self, const char *server, const char *port,

View File

@ -54,6 +54,7 @@ struct trans
struct stream* out_s;
char* listen_filename;
tis_term is_term; /* used to test for exit */
int in_write;
};
struct trans* APP_CC
@ -73,6 +74,8 @@ trans_force_read(struct trans* self, int size);
int APP_CC
trans_force_write(struct trans* self);
int APP_CC
trans_write_check(struct trans* self, int timeout);
int APP_CC
trans_connect(struct trans* self, const char* server, const char* port,
int timeout);
int APP_CC

View File

@ -293,10 +293,20 @@ send_data_from_chan_item(struct chan_item *chan_item)
out_uint32_le(s, cod->s->size);
out_uint8a(s, cod->s->p, size);
s_mark_end(s);
LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: -- "
LOGM((LOG_LEVEL_DEBUG, "chansrv::send_data_from_chan_item: -- "
"size %d chan_flags 0x%8.8x", size, chan_flags));
g_sent = 1;
error = trans_force_write(g_con_trans);
if (g_con_trans->in_write)
{
g_writeln("chansrv::send_data_from_chan_item: error, "
"write while in_write");
error = 1;
}
else
{
/* write but check for read if blocked */
error = trans_write_check(g_con_trans, -1);
}
if (error != 0)
{