samba-technical@lists.samba.org
[Top] [All Lists]

[PATCH]: Fix the bug tevent_req_poll() loops forever(was: [PATCH] (parti

Subject: [PATCH]: Fix the bug tevent_req_poll) loops forever(was: [PATCH] (partial) tevent_req_poll() loops for ever....
From: boyang
Date: Sun, 17 May 2009 00:47:13 +0800
boyang wrote:
> Jeremy Allison wrote:
>   
>> Ok, I've reviewed this carefully (with some test code) and you're
>> completely correct.
>>
>> We'll have to deal with this, I've talked to Volker and he has
>> some ideas on how to deal with this efficiently.
>>   
>>     
>
>   
Hi, everyone:
     Can someone please have a look at this? If it looks ok, I'll push
it to master. :-) Because there is change to struct cli_state, I need
someone to comment on this to see if it has any side effect, or
anything. :-)
     Thanks!
Best
          Regards
BoYang
>
>
>   


-- 
Bo Yang, Software Engineer, Suse Labs
GPG-key-ID   538C4C1A
Samba Team   boyang@xxxxxxxxx    http://www.samba.org/
Suse Linux   boyang@xxxxxxx      http://www.novell.com/

>From a3fab84169f61d564312ef2bbe04d64c10197bba Mon Sep 17 00:00:00 2001
From: Bo Yang <boyang@xxxxxxxxx>
Date: Sun, 17 May 2009 16:25:20 +0800
Subject: [PATCH] s3: Fix the bug tevent_req_poll() loops forever when
 the first send returns NT_STATUS_PIPE_BROKEN but connection
 is not teared apart. The second send over this connection will
 cause select time out and return zero, because the fd is no longer
 readable/writeable after broken. Just close fd when NT_STATUS_PIEP_BROKEN
 occurs and leave the caller to do the reconnect job.
 Signed-off-by: Bo Yang <boyang@xxxxxxxxx>

---
 lib/async_req/async_sock.c              |   10 ++
 source3/include/client.h                |    1 +
 source3/librpc/rpc/dcerpc.h             |    3 +-
 source3/libsmb/cliconnect.c             |   18 +++
 source3/libsmb/clientgen.c              |    6 +
 source3/libsmb/clifile.c                |  102 +++++++++++++++++
 source3/libsmb/clioplock.c              |    6 +
 source3/libsmb/clireadwrite.c           |   12 ++
 source3/libsmb/clitrans.c               |    6 +
 source3/rpc_client/cli_pipe.c           |  181 +++++++++++++++++++++++++++++++
 source3/rpc_client/rpc_transport_np.c   |    6 +
 source3/rpc_client/rpc_transport_smbd.c |   12 ++
 source3/rpc_server/srv_pipe_hnd.c       |    1 +
 13 files changed, 363 insertions(+), 1 deletions(-)

diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c
index 5439728..1b985e7 100644
--- a/lib/async_req/async_sock.c
+++ b/lib/async_req/async_sock.c
@@ -49,6 +49,11 @@ struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx,
        struct async_send_state *state;
        struct tevent_fd *fde;
 
+       if (fd == -1) {
+               DEBUG(10, ("socket is already closed!!!"));
+               return NULL;
+       }
+       
        result = tevent_req_create(mem_ctx, &state, struct async_send_state);
        if (result == NULL) {
                return result;
@@ -114,6 +119,11 @@ struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx,
        struct tevent_req *result;
        struct async_recv_state *state;
        struct tevent_fd *fde;
+       
+       if (fd == -1) {
+               DEBUG(10, ("socket is already disconnected!!!"));
+               return NULL;
+       }
 
        result = tevent_req_create(mem_ctx, &state, struct async_recv_state);
        if (result == NULL) {
diff --git a/source3/include/client.h b/source3/include/client.h
index 6f56468..ac40f80 100644
--- a/source3/include/client.h
+++ b/source3/include/client.h
@@ -126,6 +126,7 @@ struct rpc_pipe_client {
 
        char *desthost;
        char *srv_name_slash;
+       enum dcerpc_transport_t type;
 
        uint16 max_xmit_frag;
        uint16 max_recv_frag;
diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h
index 48019a4..072bba7 100644
--- a/source3/librpc/rpc/dcerpc.h
+++ b/source3/librpc/rpc/dcerpc.h
@@ -57,7 +57,8 @@ struct rpc_request {
 enum dcerpc_transport_t {
        NCA_UNKNOWN, NCACN_NP, NCACN_IP_TCP, NCACN_IP_UDP, NCACN_VNS_IPC, 
        NCACN_VNS_SPP, NCACN_AT_DSP, NCADG_AT_DDP, NCALRPC, NCACN_UNIX_STREAM, 
-       NCADG_UNIX_DGRAM, NCACN_HTTP, NCADG_IPX, NCACN_SPX, NCACN_INTERNAL };
+       NCADG_UNIX_DGRAM, NCACN_HTTP, NCADG_IPX, NCACN_SPX, NCACN_INTERNAL,
+       NCACN_LOCAL };
 
 
 /** this describes a binding to a particular transport/pipe */
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 16c15ce..e561068 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -341,6 +341,12 @@ static NTSTATUS cli_session_setup_guest(struct cli_state 
*cli)
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -1500,6 +1506,12 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char 
*share,
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -1797,6 +1809,12 @@ NTSTATUS cli_negprot(struct cli_state *cli)
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index bc2a092..0e49398 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -931,6 +931,12 @@ NTSTATUS cli_echo(struct cli_state *cli, uint16_t 
num_echos, DATA_BLOB data)
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 3c13383..4ab9031 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -544,6 +544,12 @@ NTSTATUS cli_rename(struct cli_state *cli, const char 
*fname_src, const char *fn
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -689,6 +695,12 @@ NTSTATUS cli_ntrename(struct cli_state *cli, const char 
*fname_src, const char *
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -754,6 +766,12 @@ NTSTATUS cli_nt_hardlink(struct cli_state *cli, const char 
*fname_src, const cha
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -865,6 +883,12 @@ NTSTATUS cli_unlink(struct cli_state *cli, const char 
*fname, uint16_t mayhave_a
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -973,6 +997,12 @@ NTSTATUS cli_mkdir(struct cli_state *cli, const char 
*dname)
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -1081,6 +1111,12 @@ NTSTATUS cli_rmdir(struct cli_state *cli, const char 
*dname)
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -1284,6 +1320,12 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -1571,6 +1613,12 @@ NTSTATUS cli_open(struct cli_state *cli, const char 
*fname, int flags,
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -1690,6 +1738,12 @@ NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum)
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -2253,6 +2307,12 @@ NTSTATUS cli_getattrE(struct cli_state *cli,
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -2401,6 +2461,12 @@ NTSTATUS cli_getatr(struct cli_state *cli,
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -2516,6 +2582,12 @@ NTSTATUS cli_setattrE(struct cli_state *cli,
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -2644,6 +2716,12 @@ NTSTATUS cli_setatr(struct cli_state *cli,
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -2767,6 +2845,12 @@ NTSTATUS cli_chkpath(struct cli_state *cli, const char 
*path)
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -2880,6 +2964,12 @@ NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, 
int *total, int *avail)
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -3544,6 +3634,12 @@ NTSTATUS cli_posix_unlink(struct cli_state *cli, const 
char *fname)
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -3611,6 +3707,12 @@ NTSTATUS cli_posix_rmdir(struct cli_state *cli, const 
char *fname)
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
diff --git a/source3/libsmb/clioplock.c b/source3/libsmb/clioplock.c
index 7350c4a..05bb79f 100644
--- a/source3/libsmb/clioplock.c
+++ b/source3/libsmb/clioplock.c
@@ -117,6 +117,12 @@ NTSTATUS cli_oplock_ack(struct cli_state *cli, uint16_t 
fnum, unsigned char leve
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index d38de19..e2b01c1 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -548,6 +548,12 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum,
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
@@ -1247,6 +1253,12 @@ NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, 
uint16_t mode,
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c
index 98c09ed..eef1d0e 100644
--- a/source3/libsmb/clitrans.c
+++ b/source3/libsmb/clitrans.c
@@ -1291,6 +1291,12 @@ NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state 
*cli,
        TALLOC_FREE(frame);
        if (!NT_STATUS_IS_OK(status)) {
                cli_set_error(cli, status);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+                       if (cli->fd != -1) {
+                               close(cli->fd);
+                               cli->fd = -1;
+                       }
+               }
        }
        return status;
 }
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 3d7db06..33b3409 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -2239,6 +2239,157 @@ static void rpc_api_pipe_req_write_done(struct 
tevent_req *subreq)
        }
 }
 
+typedef void (* close_broken_fd)(struct rpc_cli_transport *);
+
+struct broken_fd_handler_t {
+       enum dcerpc_transport_t type;
+       close_broken_fd fn;
+};
+
+/* 
+ * This is structure copied from rpc_transport_np.c, rpc_transport_tcp.c,
+ * rpc_transport_smbd.c 
+ */
+
+struct rpc_transport_np_state {
+       struct cli_state *cli;
+       const char *pipe_name;
+       uint16_t fnum;
+};
+
+struct rpc_transport_sock_state {
+       int fd;
+};
+
+struct rpc_cli_smbd_conn {
+       /**
+        * The smb connection to handle the named pipe traffic over
+        */
+       struct cli_state *cli;
+
+       /**
+        * Attached to stdout in the forked smbd, this is where smbd will
+        * print its DEBUG.
+        */
+       int stdout_fd;
+
+       /**
+        * Custom callback provided by the owner of the
+        * rpc_cli_smbd_conn. Here we send the smbd DEBUG output. Can be NULL.
+        */
+       struct {
+               void (*fn)(char *buf, size_t len, void *priv);
+               void *priv;
+       } stdout_callback ;
+};
+
+struct rpc_transport_smbd_state {
+       struct rpc_cli_smbd_conn *conn;
+       struct rpc_cli_transport *sub_transp;
+};
+
+static void close_ncacn_np(struct rpc_cli_transport *);
+static void close_ncacn_ip_tcp_or_ncalrpc(struct rpc_cli_transport *);
+static void close_ncacn_local(struct rpc_cli_transport *);
+
+static struct broken_fd_handler_t pipe_types[] = {
+       {NCA_UNKNOWN, NULL},
+       {NCACN_NP, close_ncacn_np},
+       {NCACN_IP_TCP, close_ncacn_ip_tcp_or_ncalrpc},
+       {NCACN_IP_UDP, NULL},
+       {NCACN_VNS_IPC, NULL},
+       {NCACN_VNS_SPP, NULL},
+       {NCACN_AT_DSP, NULL},
+       {NCADG_AT_DDP, NULL},
+       {NCALRPC, close_ncacn_ip_tcp_or_ncalrpc},
+       {NCACN_UNIX_STREAM, NULL},
+       {NCADG_UNIX_DGRAM, NULL},
+       {NCACN_HTTP, NULL},
+       {NCADG_IPX, NULL},
+       {NCACN_SPX, NULL},
+       {NCACN_INTERNAL, NULL},
+       {NCACN_LOCAL, close_ncacn_local},
+       {-1, NULL}
+};
+
+static void close_ncacn_np(struct rpc_cli_transport *transport)
+{
+       struct rpc_transport_np_state *np_state = NULL;
+       struct cli_state *client = NULL;
+       
+       if (!transport) {
+               return;
+       }
+       np_state = talloc_get_type_abort(transport->priv,
+                       struct rpc_transport_np_state);
+
+       if (!np_state) {
+               return;
+       }
+       client = np_state->cli;
+
+       if (client && (client->fd != -1)) {
+               close(client->fd);
+               client->fd = -1;
+       }
+}
+
+static void close_ncacn_ip_tcp_or_ncalrpc(struct rpc_cli_transport *transport)
+{
+       struct rpc_transport_sock_state *sk_state = NULL;
+       
+       if (!transport) {
+               return;
+       }
+       sk_state = talloc_get_type_abort(transport->priv,
+                       struct rpc_transport_sock_state);
+
+       if (sk_state && (sk_state->fd != -1)) {
+               close(sk_state->fd);
+               sk_state->fd = -1;
+       }
+}
+
+static void close_ncacn_local(struct rpc_cli_transport *transport)
+{
+       struct rpc_transport_smbd_state *smbd_state = NULL;
+       struct rpc_cli_smbd_conn *conn = NULL;
+       struct cli_state *client = NULL;
+       
+       if (!transport) {
+               return;
+       }
+       smbd_state = talloc_get_type_abort(transport->priv,
+                       struct rpc_transport_smbd_state);
+
+       if (!smbd_state) {
+               return;
+       }
+       conn = smbd_state->conn;
+
+       if (!conn) {
+               return;
+       }
+       client = conn->cli;
+
+       if (client && client->fd != -1) {
+               close(client->fd);
+               client->fd = -1;
+       }
+}
+
+static void close_broken_pipe_fd(struct rpc_pipe_client *cli)
+{
+       struct rpc_cli_transport *transport = cli->transport;
+       if (cli->type < 0 || cli->type > NCACN_LOCAL) {
+               return;
+       }
+
+       if (pipe_types[cli->type].fn) {
+               pipe_types[cli->type].fn(transport);
+       }
+}
+
 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
@@ -2314,6 +2465,19 @@ NTSTATUS rpc_api_pipe_req(TALLOC_CTX *mem_ctx, struct 
rpc_pipe_client *cli,
        status = rpc_api_pipe_req_recv(req, mem_ctx, out_data);
  fail:
        TALLOC_FREE(frame);
+       
+       /* 
+        * if the returned status is NT_STATUS_PIPE_BROKEN, the other end
+        * might be closed. we have to close the socket, otherwise, it causes 
+        * tevent_req_poll() loops forever. Because select will always timeout
+        * and return zero(the fd is no logner be readable or writeable). But
+        * we have to distinguish among named pipe, drsuapi(rpc over tcp), 
local rpc
+        * and ncalrpc. Do we have a better idea to distinguish them?
+        */
+       if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+               close_broken_pipe_fd(cli);
+       }
+
        return status;
 }
 
@@ -2933,6 +3097,19 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
        status = rpc_pipe_bind_recv(req);
  fail:
        TALLOC_FREE(frame);
+       
+       /* 
+        * if the returned status is NT_STATUS_PIPE_BROKEN, the other end
+        * might be closed. we have to close the socket, otherwise, it causes 
+        * tevent_req_poll() loops forever. Because select will always timeout
+        * and return zero(the fd is no logner be readable or writeable). But
+        * we have to distinguish among named pipe, drsuapi(rpc over tcp), 
local rpc
+        * and ncalrpc. Do we have a better idea to distinguish them?
+        */
+       if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+               close_broken_pipe_fd(cli);
+       }
+
        return status;
 }
 
@@ -3191,6 +3368,7 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX 
*mem_ctx, const char *host,
        result->abstract_syntax = *abstract_syntax;
        result->transfer_syntax = ndr_transfer_syntax;
        result->dispatch = cli_do_rpc_ndr;
+       result->type = NCACN_IP_TCP;
 
        result->desthost = talloc_strdup(result, host);
        result->srv_name_slash = talloc_asprintf_strupper_m(
@@ -3403,6 +3581,7 @@ NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const 
char *socket_path,
        result->abstract_syntax = *abstract_syntax;
        result->transfer_syntax = ndr_transfer_syntax;
        result->dispatch = cli_do_rpc_ndr;
+       result->type = NCALRPC;
 
        result->desthost = get_myname(result);
        result->srv_name_slash = talloc_asprintf_strupper_m(
@@ -3491,6 +3670,7 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
        result->abstract_syntax = *abstract_syntax;
        result->transfer_syntax = ndr_transfer_syntax;
        result->dispatch = cli_do_rpc_ndr;
+       result->type = NCACN_NP;
        result->desthost = talloc_strdup(result, cli->desthost);
        result->srv_name_slash = talloc_asprintf_strupper_m(
                result, "\\\\%s", result->desthost);
@@ -3535,6 +3715,7 @@ NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
        result->dispatch = cli_do_rpc_ndr;
        result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
        result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
+       result->type = NCACN_LOCAL;
 
        result->desthost = talloc_strdup(result, global_myname());
        result->srv_name_slash = talloc_asprintf_strupper_m(
diff --git a/source3/rpc_client/rpc_transport_np.c 
b/source3/rpc_client/rpc_transport_np.c
index 73d23d8..9d85766 100644
--- a/source3/rpc_client/rpc_transport_np.c
+++ b/source3/rpc_client/rpc_transport_np.c
@@ -389,6 +389,12 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct 
cli_state *cli,
        status = rpc_transport_np_init_recv(req, mem_ctx, presult);
  fail:
        TALLOC_FREE(frame);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+               if (cli->fd != -1) {
+                       close(cli->fd);
+                       cli->fd = -1;
+               }
+       }
        return status;
 }
 
diff --git a/source3/rpc_client/rpc_transport_smbd.c 
b/source3/rpc_client/rpc_transport_smbd.c
index 171048a..c4d39b9 100644
--- a/source3/rpc_client/rpc_transport_smbd.c
+++ b/source3/rpc_client/rpc_transport_smbd.c
@@ -416,6 +416,12 @@ NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx,
        status = rpc_cli_smbd_conn_init_recv(req, mem_ctx, pconn);
  fail:
        TALLOC_FREE(frame);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+               if ((*pconn)->cli->fd != -1) {
+                       close((*pconn)->cli->fd);
+                       (*pconn)->cli->fd = -1;
+               }
+       }
        return status;
 }
 
@@ -680,5 +686,11 @@ NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx,
        status = rpc_transport_smbd_init_recv(req, mem_ctx, presult);
  fail:
        TALLOC_FREE(frame);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_BROKEN)) {
+               if (conn->cli->fd != -1) {
+                       close(conn->cli->fd);
+                       conn->cli->fd = -1;
+               }
+       }
        return status;
 }
diff --git a/source3/rpc_server/srv_pipe_hnd.c 
b/source3/rpc_server/srv_pipe_hnd.c
index f244161..01fd9cb 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -1466,6 +1466,7 @@ NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx,
        result->abstract_syntax = *abstract_syntax;
        result->transfer_syntax = ndr_transfer_syntax;
        result->dispatch = dispatch;
+       result->type = NCACN_INTERNAL;
 
        result->pipes_struct = make_internal_rpc_pipe_p(
                result, abstract_syntax, "", serversupplied_info);
-- 
1.5.3

<Prev in Thread] Current Thread [Next in Thread>