]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stream-int: Remove SI_FL_NOLINGER/NOHALF to rely on CS flags instead
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 30 Mar 2022 13:10:18 +0000 (15:10 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 13 Apr 2022 13:10:14 +0000 (15:10 +0200)
Flags to disable lingering and half-close are now handled at the conn-stream
level. Thus SI_FL_NOLINGER and SI_FL_NOHALF stream-int flags are replaced by
CS_FL_NOLINGER and CS_FL_NOHALF conn-stream flags.

14 files changed:
dev/flags/flags.c
include/haproxy/conn_stream-t.h
include/haproxy/stream_interface-t.h
src/backend.c
src/cli.c
src/dns.c
src/http_ana.c
src/http_client.c
src/peers.c
src/sink.c
src/stream.c
src/stream_interface.c
src/tcp_act.c
src/tcp_rules.c

index 5473903ceb5c2a917aa2f96cde5f42aac41e1863..8317b7550e832b537080ad716ae41cb5ed098f4b 100644 (file)
@@ -219,6 +219,8 @@ void show_cs_flags(unsigned int f)
                printf("0\n");
                return;
        }
+       SHOW_FLAG(f, CS_FL_NOLINGER);
+       SHOW_FLAG(f, CS_FL_NOHALF);
        SHOW_FLAG(f, CS_FL_ADDR_FROM_SET);
        SHOW_FLAG(f, CS_FL_ADDR_TO_SET);
        SHOW_FLAG(f, CS_FL_ISBACK);
@@ -267,8 +269,6 @@ void show_si_flags(unsigned int f)
        SHOW_FLAG(f, SI_FL_ISBACK);
        SHOW_FLAG(f, SI_FL_DONT_WAKE);
        SHOW_FLAG(f, SI_FL_INDEP_STR);
-       SHOW_FLAG(f, SI_FL_NOLINGER);
-       SHOW_FLAG(f, SI_FL_NOHALF);
        SHOW_FLAG(f, SI_FL_SRC_ADDR);
        SHOW_FLAG(f, SI_FL_WANT_GET);
        SHOW_FLAG(f, SI_FL_CLEAN_ABRT);
index 55f338b095b1a33f2a59a58e61cfdf45bfabf85a..877bace13ac08a78da549d53bf556e6606fc58e3 100644 (file)
@@ -82,6 +82,9 @@ enum {
 
        CS_FL_ADDR_FROM_SET = 0x00000002, /* source address is set */
        CS_FL_ADDR_TO_SET   = 0x00000004, /* destination address is set */
+
+       CS_FL_NOLINGER      = 0x00000008,  /* may close without lingering. One-shot. */
+       CS_FL_NOHALF        = 0x00000010,  /* no half close, close both sides at once */
 };
 
 /* cs_shutr() modes */
index 7766f4cb54e2bdb273849771658632aeb3242b32..ebd9d3515e828f2d90ecbfa1a7a64389dc90531f 100644 (file)
@@ -88,8 +88,6 @@ enum {
        SI_FL_ISBACK     = 0x00000010,  /* 0 for front-side SI, 1 for back-side */
        SI_FL_DONT_WAKE  = 0x00000020,  /* resync in progress, don't wake up */
        SI_FL_INDEP_STR  = 0x00000040,  /* independent streams = don't update rex on write */
-       SI_FL_NOLINGER   = 0x00000080,  /* may close without lingering. One-shot. */
-       SI_FL_NOHALF     = 0x00000100,  /* no half close, close both sides at once */
        SI_FL_SRC_ADDR   = 0x00001000,  /* get the source ip/port with getsockname */
        /* unused: 0x00000200 */
        SI_FL_WANT_GET   = 0x00004000,  /* a stream-int would like to get some data from the buffer */
index 5429e352af76b69a370b9bc86e223788837ee204..56e3c17801695544b7d7d75d6aec8f79212d87f8 100644 (file)
@@ -1641,7 +1641,7 @@ skip_reuse:
 
        /* disable lingering */
        if (s->be->options & PR_O_TCP_NOLING)
-               cs_si(s->csb)->flags |= SI_FL_NOLINGER;
+               s->csb->flags |= CS_FL_NOLINGER;
 
        if (s->flags & SF_SRV_REUSED) {
                _HA_ATOMIC_INC(&s->be->be_counters.reuse);
@@ -2175,7 +2175,7 @@ void back_handle_st_con(struct stream *s)
        if ((rep->flags & CF_SHUTW) ||
            ((req->flags & CF_SHUTW_NOW) &&
             (channel_is_empty(req) || (s->be->options & PR_O_ABRT_CLOSE)))) {
-               cs->si->flags |= SI_FL_NOLINGER;
+               cs->flags |= CS_FL_NOLINGER;
                si_shutw(cs->si);
                cs->si->err_type |= SI_ET_CONN_ABRT;
                if (s->srv_error)
@@ -2391,7 +2391,7 @@ void back_handle_st_rdy(struct stream *s)
                    ((req->flags & CF_SHUTW_NOW) &&
                     (channel_is_empty(req) || (s->be->options & PR_O_ABRT_CLOSE)))) {
                        /* give up */
-                       cs->si->flags |= SI_FL_NOLINGER;
+                       cs->flags |= CS_FL_NOLINGER;
                        si_shutw(cs->si);
                        cs->si->err_type |= SI_ET_CONN_ABRT;
                        if (s->srv_error)
index 56629b0ec236a1b0f32b1038cda2c87029f9e45d..4d0e293fc3d634b47affa8c4c1dc56997a2c48ac 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -2684,7 +2684,7 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
 
                pcli_write_prompt(s);
 
-               cs_si(s->csb)->flags |= SI_FL_NOLINGER | SI_FL_NOHALF;
+               s->csb->flags |= CS_FL_NOLINGER | CS_FL_NOHALF;
                si_shutr(cs_si(s->csb));
                si_shutw(cs_si(s->csb));
 
index 92f37b4f7ccdc78e97c101f7c33ec7db0c5d37aa..f60639a7d4fc669ce719b2bba46989f7a3ca9344 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -916,7 +916,7 @@ static struct appctx *dns_session_create(struct dns_session *ds)
 
        s = DISGUISE(cs_strm(cs));
        s->csb->dst = addr;
-       cs_si(s->csb)->flags |= SI_FL_NOLINGER;
+       s->csb->flags |= CS_FL_NOLINGER;
        s->target = &ds->dss->srv->obj_type;
        s->flags = SF_ASSIGNED|SF_ADDR_SET;
 
index a1b6b1fdb4af467cd84773a16d19b7f3e2682f7f..c1700f2f947ff4668ee5455ebb8bd7520ee4981b 100644 (file)
@@ -1112,7 +1112,7 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
        if (s->be->options & PR_O_ABRT_CLOSE) {
                channel_auto_read(req);
                if ((req->flags & (CF_SHUTR|CF_READ_NULL)) && !(txn->flags & TX_CON_WANT_TUN))
-                       cs_si(s->csb)->flags |= SI_FL_NOLINGER;
+                       s->csb->flags |= CS_FL_NOLINGER;
                channel_auto_close(req);
        }
        else if (s->txn->meth == HTTP_METH_POST) {
@@ -1358,7 +1358,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
                                stream_inc_http_fail_ctr(s);
                        }
 
-                       si_b->flags |= SI_FL_NOLINGER;
+                       s->csb->flags |= CS_FL_NOLINGER;
                        http_reply_and_close(s, txn->status, http_error_message(s));
 
                        if (!(s->flags & SF_ERR_MASK))
@@ -1388,7 +1388,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
 
                        txn->status = 504;
                        stream_inc_http_fail_ctr(s);
-                       si_b->flags |= SI_FL_NOLINGER;
+                       s->csb->flags |= CS_FL_NOLINGER;
                        http_reply_and_close(s, txn->status, http_error_message(s));
 
                        if (!(s->flags & SF_ERR_MASK))
@@ -1445,7 +1445,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
 
                        txn->status = 502;
                        stream_inc_http_fail_ctr(s);
-                       si_b->flags |= SI_FL_NOLINGER;
+                       s->csb->flags |= CS_FL_NOLINGER;
                        http_reply_and_close(s, txn->status, http_error_message(s));
 
                        if (!(s->flags & SF_ERR_MASK))
@@ -1740,7 +1740,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
        if (!(s->flags & SF_FINST_MASK))
                s->flags |= SF_FINST_H;
 
-       si_b->flags |= SI_FL_NOLINGER;
+       s->csb->flags |= CS_FL_NOLINGER;
        DBG_TRACE_DEVEL("leaving on error",
                        STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
        return 0;
@@ -2050,7 +2050,7 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
 
  return_prx_cond:
        s->logs.t_data = -1; /* was not a valid response */
-       cs_si(s->csb)->flags |= SI_FL_NOLINGER;
+       s->csb->flags |= CS_FL_NOLINGER;
 
        if (!(s->flags & SF_ERR_MASK))
                s->flags |= SF_ERR_PRXCOND;
@@ -4318,7 +4318,7 @@ static void http_end_request(struct stream *s)
                /* if the server closes the connection, we want to immediately react
                 * and close the socket to save packets and syscalls.
                 */
-               cs_si(s->csb)->flags |= SI_FL_NOHALF;
+               s->csb->flags |= CS_FL_NOHALF;
 
                /* In any case we've finished parsing the request so we must
                 * disable Nagle when sending data because 1) we're not going
@@ -4393,7 +4393,7 @@ static void http_end_request(struct stream *s)
          http_msg_closed:
                /* if we don't know whether the server will close, we need to hard close */
                if (txn->rsp.flags & HTTP_MSGF_XFER_LEN)
-                       cs_si(s->csb)->flags |= SI_FL_NOLINGER;  /* we want to close ASAP */
+                       s->csb->flags |= CS_FL_NOLINGER;  /* we want to close ASAP */
                /* see above in MSG_DONE why we only do this in these states */
                if (!(s->be->options & PR_O_ABRT_CLOSE))
                        channel_dont_read(chn);
index 83faffed25aa1bab07576d2409aa812147c56ddb..7adc82de9e49fdb6470a0be55b8da0fd8db5d068 100644 (file)
@@ -526,7 +526,7 @@ struct appctx *httpclient_start(struct httpclient *hc)
        }
 
        s->csb->dst = addr;
-       cs_si(s->csb)->flags |= SI_FL_NOLINGER;
+       s->csb->flags |= CS_FL_NOLINGER;
        s->flags |= SF_ASSIGNED|SF_ADDR_SET;
        s->res.flags |= CF_READ_DONTWAIT;
 
index 4d86126f216e9cdb78a08119aade788bf8a3b526..7c40e4541331ae6ef758b17ae7cde1dd5c2422cf 100644 (file)
@@ -3210,7 +3210,7 @@ static struct appctx *peer_session_create(struct peers *peers, struct peer *peer
 
        /* initiate an outgoing connection */
        s->csb->dst = addr;
-       cs_si(s->csb)->flags |= SI_FL_NOLINGER;
+       s->csb->flags |= CS_FL_NOLINGER;
        s->flags = SF_ASSIGNED|SF_ADDR_SET;
        s->target = peer_session_target(peer, s);
 
index e7ad4bd0356f45fbd4e6e909db95becf1ad00192..8dfe33e9f6ee876231945701f244de2375d9ab57 100644 (file)
@@ -657,7 +657,7 @@ static struct appctx *sink_forward_session_create(struct sink *sink, struct sink
        s = DISGUISE(cs_strm(cs));
 
        s->csb->dst = addr;
-       cs_si(s->csb)->flags |= SI_FL_NOLINGER;
+       s->csb->flags |= CS_FL_NOLINGER;
 
        s->target = &sft->srv->obj_type;
        s->flags = SF_ASSIGNED|SF_ADDR_SET;
index fbf32ebcf43234c61a69d850e910217bdd4094ce..a42c8968f9401654b116f1d35186a2021fcda957 100644 (file)
@@ -1638,26 +1638,26 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
                channel_check_timeouts(req);
 
                if (unlikely((req->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
-                       si_b->flags |= SI_FL_NOLINGER;
+                       s->csb->flags |= CS_FL_NOLINGER;
                        si_shutw(si_b);
                }
 
                if (unlikely((req->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
-                       if (si_f->flags & SI_FL_NOHALF)
-                               si_f->flags |= SI_FL_NOLINGER;
+                       if (s->csf->flags & CS_FL_NOHALF)
+                               s->csf->flags |= CS_FL_NOLINGER;
                        si_shutr(si_f);
                }
 
                channel_check_timeouts(res);
 
                if (unlikely((res->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
-                       si_f->flags |= SI_FL_NOLINGER;
+                       s->csf->flags |= CS_FL_NOLINGER;
                        si_shutw(si_f);
                }
 
                if (unlikely((res->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
-                       if (si_b->flags & SI_FL_NOHALF)
-                               si_b->flags |= SI_FL_NOLINGER;
+                       if (s->csb->flags & CS_FL_NOHALF)
+                               s->csb->flags |= CS_FL_NOLINGER;
                        si_shutr(si_b);
                }
 
@@ -2236,7 +2236,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
        if (unlikely((req->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
                     channel_is_empty(req))) {
                if (req->flags & CF_READ_ERROR)
-                       si_b->flags |= SI_FL_NOLINGER;
+                       s->csb->flags |= CS_FL_NOLINGER;
                si_shutw(si_b);
        }
 
@@ -2247,8 +2247,8 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
 
        /* shutdown(read) pending */
        if (unlikely((req->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
-               if (si_f->flags & SI_FL_NOHALF)
-                       si_f->flags |= SI_FL_NOLINGER;
+               if (s->csf->flags & CS_FL_NOHALF)
+                       s->csf->flags |= CS_FL_NOLINGER;
                si_shutr(si_f);
        }
 
@@ -2372,8 +2372,8 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
 
        /* shutdown(read) pending */
        if (unlikely((res->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
-               if (si_b->flags & SI_FL_NOHALF)
-                       si_b->flags |= SI_FL_NOLINGER;
+               if (s->csb->flags & CS_FL_NOHALF)
+                       s->csb->flags |= CS_FL_NOLINGER;
                si_shutr(si_b);
        }
 
index dcbe1a1720f8386d689310d480f7050942612614..2c196ce4416e9fdecd954b15dc5184781ca19091 100644 (file)
@@ -162,7 +162,7 @@ void si_retnclose(struct stream_interface *si,
  * This function performs a shutdown-read on a detached stream interface in a
  * connected or init state (it does nothing for other states). It either shuts
  * the read side or marks itself as closed. The buffer flags are updated to
- * reflect the new state. If the stream interface has SI_FL_NOHALF, we also
+ * reflect the new state. If the stream interface has CS_FL_NOHALF, we also
  * forward the close to the write side. The owner task is woken up if it exists.
  */
 static void stream_int_shutr(struct stream_interface *si)
@@ -182,7 +182,7 @@ static void stream_int_shutr(struct stream_interface *si)
                si->state = SI_ST_DIS;
                __cs_strm(si->cs)->conn_exp = TICK_ETERNITY;
        }
-       else if (si->flags & SI_FL_NOHALF) {
+       else if (si->cs->flags & CS_FL_NOHALF) {
                /* we want to immediately forward this close to the write side */
                return stream_int_shutw(si);
        }
@@ -222,10 +222,10 @@ static void stream_int_shutw(struct stream_interface *si)
                /* we have to shut before closing, otherwise some short messages
                 * may never leave the system, especially when there are remaining
                 * unread data in the socket input buffer, or when nolinger is set.
-                * However, if SI_FL_NOLINGER is explicitly set, we know there is
+                * However, if CS_FL_NOLINGER is explicitly set, we know there is
                 * no risk so we close both sides immediately.
                 */
-               if (!(si->cs->endp->flags & CS_EP_ERROR) && !(si->flags & SI_FL_NOLINGER) &&
+               if (!(si->cs->endp->flags & CS_EP_ERROR) && !(si->cs->flags & CS_FL_NOLINGER) &&
                    !(ic->flags & (CF_SHUTR|CF_DONT_READ)))
                        return;
 
@@ -238,7 +238,7 @@ static void stream_int_shutw(struct stream_interface *si)
                si->state = SI_ST_DIS;
                /* fall through */
        default:
-               si->flags &= ~SI_FL_NOLINGER;
+               si->cs->flags &= ~CS_FL_NOLINGER;
                si_rx_shut_blk(si);
                ic->flags |= CF_SHUTR;
                ic->rex = TICK_ETERNITY;
@@ -1017,7 +1017,7 @@ void si_update_both(struct stream_interface *si_f, struct stream_interface *si_b
  * a connection in a connected or init state (it does nothing for other
  * states). It either shuts the read side or marks itself as closed. The buffer
  * flags are updated to reflect the new state. If the stream interface has
- * SI_FL_NOHALF, we also forward the close to the write side. If a control
+ * CS_FL_NOHALF, we also forward the close to the write side. If a control
  * layer is defined, then it is supposed to be a socket layer and file
  * descriptors are then shutdown or closed accordingly. The function
  * automatically disables polling if needed.
@@ -1043,7 +1043,7 @@ static void stream_int_shutr_conn(struct stream_interface *si)
                si->state = SI_ST_DIS;
                __cs_strm(cs)->conn_exp = TICK_ETERNITY;
        }
-       else if (si->flags & SI_FL_NOHALF) {
+       else if (si->cs->flags & CS_FL_NOHALF) {
                /* we want to immediately forward this close to the write side */
                return stream_int_shutw_conn(si);
        }
@@ -1083,14 +1083,14 @@ static void stream_int_shutw_conn(struct stream_interface *si)
                /* we have to shut before closing, otherwise some short messages
                 * may never leave the system, especially when there are remaining
                 * unread data in the socket input buffer, or when nolinger is set.
-                * However, if SI_FL_NOLINGER is explicitly set, we know there is
+                * However, if CS_FL_NOLINGER is explicitly set, we know there is
                 * no risk so we close both sides immediately.
                 */
 
                if (cs->endp->flags & CS_EP_ERROR) {
                        /* quick close, the socket is already shut anyway */
                }
-               else if (si->flags & SI_FL_NOLINGER) {
+               else if (cs->flags & CS_FL_NOLINGER) {
                        /* unclean data-layer shutdown, typically an aborted request
                         * or a forwarded shutdown from a client to a server due to
                         * option abortonclose. No need for the TLS layer to try to
@@ -1124,7 +1124,7 @@ static void stream_int_shutw_conn(struct stream_interface *si)
                si->state = SI_ST_DIS;
                /* fall through */
        default:
-               si->flags &= ~SI_FL_NOLINGER;
+               cs->flags &= ~CS_FL_NOLINGER;
                si_rx_shut_blk(si);
                ic->flags |= CF_SHUTR;
                ic->rex = TICK_ETERNITY;
@@ -1574,7 +1574,7 @@ static int si_cs_recv(struct conn_stream *cs)
 
 /*
  * This function propagates a null read received on a socket-based connection.
- * It updates the stream interface. If the stream interface has SI_FL_NOHALF,
+ * It updates the stream interface. If the stream interface has CS_FL_NOHALF,
  * the close is also forwarded to the write side as an abort.
  */
 static void stream_int_read0(struct stream_interface *si)
@@ -1597,7 +1597,7 @@ static void stream_int_read0(struct stream_interface *si)
        if (oc->flags & CF_SHUTW)
                goto do_close;
 
-       if (si->flags & SI_FL_NOHALF) {
+       if (cs->flags & CS_FL_NOHALF) {
                /* we want to immediately forward this close to the write side */
                /* force flag on ssl to keep stream in cache */
                cs_shutw(cs, CS_SHW_SILENT);
@@ -1663,7 +1663,7 @@ void si_applet_wake_cb(struct stream_interface *si)
  * This function performs a shutdown-read on a stream interface attached to an
  * applet in a connected or init state (it does nothing for other states). It
  * either shuts the read side or marks itself as closed. The buffer flags are
- * updated to reflect the new state. If the stream interface has SI_FL_NOHALF,
+ * updated to reflect the new state. If the stream interface has CS_FL_NOHALF,
  * we also forward the close to the write side. The owner task is woken up if
  * it exists.
  */
@@ -1689,7 +1689,7 @@ static void stream_int_shutr_applet(struct stream_interface *si)
                si->state = SI_ST_DIS;
                __cs_strm(si->cs)->conn_exp = TICK_ETERNITY;
        }
-       else if (si->flags & SI_FL_NOHALF) {
+       else if (si->cs->flags & CS_FL_NOHALF) {
                /* we want to immediately forward this close to the write side */
                return stream_int_shutw_applet(si);
        }
@@ -1730,10 +1730,10 @@ static void stream_int_shutw_applet(struct stream_interface *si)
                /* we have to shut before closing, otherwise some short messages
                 * may never leave the system, especially when there are remaining
                 * unread data in the socket input buffer, or when nolinger is set.
-                * However, if SI_FL_NOLINGER is explicitly set, we know there is
+                * However, if CS_FL_NOLINGER is explicitly set, we know there is
                 * no risk so we close both sides immediately.
                 */
-               if (!(si->cs->endp->flags & CS_EP_ERROR) && !(si->flags & SI_FL_NOLINGER) &&
+               if (!(si->cs->endp->flags & CS_EP_ERROR) && !(si->cs->flags & CS_FL_NOLINGER) &&
                    !(ic->flags & (CF_SHUTR|CF_DONT_READ)))
                        return;
 
@@ -1747,7 +1747,7 @@ static void stream_int_shutw_applet(struct stream_interface *si)
                si->state = SI_ST_DIS;
                /* fall through */
        default:
-               si->flags &= ~SI_FL_NOLINGER;
+               si->cs->flags &= ~CS_FL_NOLINGER;
                si_rx_shut_blk(si);
                ic->flags |= CF_SHUTR;
                ic->rex = TICK_ETERNITY;
index 00505150909e6563685a64fdb663046de164a246..19e7eeaf88dfc2201c88081437373a333eb7b625 100644 (file)
@@ -289,7 +289,7 @@ static enum act_return tcp_exec_action_silent_drop(struct act_rule *rule, struct
         * is present, returning with ERR will cause lingering to be disabled.
         */
        if (strm)
-               strm->csf->si->flags |= SI_FL_NOLINGER;
+               strm->csf->flags |= CS_FL_NOLINGER;
 
        if (conn->flags & CO_FL_FDLESS)
                goto out;
index 6c45f483e03da90addb6016326af6c42b8d11bfc..4293cbda16d3d60c63d874d8597fb73c4abcbc10 100644 (file)
@@ -392,7 +392,7 @@ resume_execution:
                                goto deny;
                        }
                        else if (rule->action == ACT_TCP_CLOSE) {
-                               chn_prod(rep)->si->flags |= SI_FL_NOLINGER | SI_FL_NOHALF;
+                               chn_prod(rep)->flags |= CS_FL_NOLINGER | CS_FL_NOHALF;
                                cs_must_kill_conn(chn_prod(rep));
                                si_shutr(chn_prod(rep)->si);
                                si_shutw(chn_prod(rep)->si);