if (w < 0) {
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
return;
+ c->err = errno;
goto close;
- }
- else if (w == 0)
+ } else if (w == 0)
goto close;
else if (c->len == CHAN_BUFSZ && !(c->f & CHANF_CLOSE))
sel_addfile(&c->r);
if (r < 0) {
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
return;
+ c->err = errno;
goto close;
- }
- else if (r == 0)
+ } else if (r == 0)
goto close;
else if (c->len == 0 && (c->f & CHANF_READY)) {
sel_addfile(&c->w);
typedef struct tango {
struct tango *next, *prev; /* A big list of all tangos */
endpt *a, *b; /* The two endpoints */
+ char *desc; /* Description of the connection */
unsigned s; /* State of the connection */
chanpair *c; /* The pair of channels */
} tango;
*/
if (a->f & b->f & EPF_FILE) {
+ if (t->c->ab.err)
+ fw_log(-1, "[%s] error: %s", t->desc, strerror(t->c->ab.err));
+ else if (t->c->ba.err)
+ fw_log(-1, "[%s] error: %s", t->desc, strerror(t->c->ba.err));
if (t->s & EPS_AB)
chan_close(&t->c->ab);
if (!(b->f & EPF_PENDING) && (t->s & EPS_BA))
t->prev->next = t->next;
else
tangos = t->next;
+ if (t->desc)
+ xfree(t->desc);
DESTROY(t);
}
*
* Arguments: @endpt *a@ = pointer to first endpoint
* @endpt *b@ = pointer to second endpoint
+ * @const char *desc@ = description of connection
*
* Returns: ---
*
* which are already joined; in fact, the the right thing to do
* when your endpoint decides that it's not pending any more is
* to join it to its partner again.
+ *
+ * If the endpoints are already connected then the description
+ * string is ignored. The endpoint manager takes a copy of the
+ * string, so you don't need to keep it around.
*/
-void endpt_join(endpt *a, endpt *b)
+void endpt_join(endpt *a, endpt *b, const char *desc)
{
tango *t = a->t;
a->t = b->t = t;
t->s = EPS_AB | EPS_BA;
t->c = 0;
+ t->desc = xstrdup(desc);
if (tangos)
tangos->prev = t;
tangos = t;
ee->ops->close(ee);
goto tidy;
}
- endpt_join(e, ee);
+ endpt_join(e, ee, xs->s.desc);
/* --- Dispose of source and target --- */
ee->ops->close(ee);
goto tidy;
}
- endpt_join(e, ee);
+ endpt_join(e, ee, fs->s.desc);
/* --- Dispose of the source and target now --- */
unsigned base, len; /* Base and length of data */
unsigned f; /* Various interesting flags */
void (*func)(void */*p*/); /* Function to call on closure */
+ int err; /* What's wrong with the channel */
void *p; /* Argument to pass function */
sel_file r, w; /* Reader and writer selectors */
char buf[CHAN_BUFSZ]; /* The actual data buffer */
*
* Arguments: @endpt *a@ = pointer to first endpoint
* @endpt *b@ = pointer to second endpoint
+ * @const char *desc@ = description of connection
*
* Returns: ---
*
- * Use: Joins two endpoints together.
+ * Use: Joins two endpoints together. It's OK to join endpoints
+ * which are already joined; in fact, the the right thing to do
+ * when your endpoint decides that it's not pending any more is
+ * to join it to its partner again.
+ *
+ * If the endpoints are already connected then the description
+ * string is ignored. The endpoint manager takes a copy of
+ * the string, so you don't need to keep it around.
*/
-extern void endpt_join(endpt */*a*/, endpt */*b*/);
+extern void endpt_join(endpt */*a*/, endpt */*b*/, const char */*desc*/);
/* --- @source_add@ --- *
*
e->e.in = e->e.out = r;
e->e.f &= ~EPF_PENDING;
if (e->e.other)
- endpt_join(&e->e, e->e.other);
+ endpt_join(&e->e, e->e.other, 0);
}
}
/* --- Let everything else happen --- */
- endpt_join(&e->e, ee);
+ endpt_join(&e->e, ee, ss->s.desc);
}
}