FD_ST_READY
};
+
+/* This is the value used to mark a file descriptor as dead. This value is
+ * negative, this is important so that tests on fd < 0 properly match. It
+ * also has the nice property of being highly negative but not overflowing
+ * nor changing sign on 32-bit machines when multipled by sizeof(fdtab).
+ * This ensures that any unexpected dereference of such an uninitialized
+ * file descriptor will lead to so large a dereference that it will crash
+ * the process at the exact location of the bug with a clean stack trace
+ * instead of causing silent manipulation of other FDs. And it's readable
+ * when found in a dump.
+ */
+#define DEAD_FD_MAGIC 0xFDDEADFD
+
/* info about one given fd */
struct fdtab {
void (*iocb)(int fd); /* I/O handler */
obj_type_name(conn->target),
obj_base_ptr(conn->target));
- chunk_appendf(&trash,
- " flags=0x%08x fd=%d fd.state=%02x fd.cache=%d updt=%d\n",
- conn->flags,
- conn->t.sock.fd,
- conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].state : 0,
- conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].cache : 0,
- conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].updated : 0);
+ chunk_appendf(&trash, " flags=0x%08x", conn->flags);
+
+ if (conn->t.sock.fd >= 0) {
+ chunk_appendf(&trash, " fd=%d fd.state=%02x fd.cache=%d updt=%d\n",
+ conn->t.sock.fd, fdtab[conn->t.sock.fd].state,
+ fdtab[conn->t.sock.fd].cache, fdtab[conn->t.sock.fd].updated);
+ }
+ else
+ chunk_appendf(&trash, " fd=<dead>\n");
}
else if ((tmpctx = objt_appctx(sess->si[0].end)) != NULL) {
chunk_appendf(&trash,
obj_type_name(conn->target),
obj_base_ptr(conn->target));
- chunk_appendf(&trash,
- " flags=0x%08x fd=%d fd.state=%02x fd.cache=%d updt=%d\n",
- conn->flags,
- conn->t.sock.fd,
- conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].state : 0,
- conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].cache : 0,
- conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].updated : 0);
+ chunk_appendf(&trash, " flags=0x%08x", conn->flags);
+
+ if (conn->t.sock.fd >= 0) {
+ chunk_appendf(&trash, " fd=%d fd.state=%02x fd.cache=%d updt=%d\n",
+ conn->t.sock.fd, fdtab[conn->t.sock.fd].state,
+ fdtab[conn->t.sock.fd].cache, fdtab[conn->t.sock.fd].updated);
+ }
+ else
+ chunk_appendf(&trash, " fd=<dead>\n");
}
else if ((tmpctx = objt_appctx(sess->si[1].end)) != NULL) {
chunk_appendf(&trash,
" s0=[%d,%1xh,fd=%d,ex=%s]",
curr_sess->si[0].state,
curr_sess->si[0].flags,
- conn ? conn->t.sock.fd : -1,
+ (conn && conn->t.sock.fd >= 0) ? conn->t.sock.fd : -1,
curr_sess->si[0].exp ?
human_time(TICKS_TO_MS(curr_sess->si[0].exp - now_ms),
TICKS_TO_MS(1000)) : "");
" s1=[%d,%1xh,fd=%d,ex=%s]",
curr_sess->si[1].state,
curr_sess->si[1].flags,
- conn ? conn->t.sock.fd : -1,
+ (conn && conn->t.sock.fd >= 0) ? conn->t.sock.fd : -1,
curr_sess->si[1].exp ?
human_time(TICKS_TO_MS(curr_sess->si[1].exp - now_ms),
TICKS_TO_MS(1000)) : "");