diff options
author | Volker Lendecke <vl@samba.org> | 2011-07-26 19:44:51 +0200 |
---|---|---|
committer | Volker Lendecke <vlendec@samba.org> | 2011-07-27 00:47:45 +0200 |
commit | 1335059ff5ef1a8f0f9aedf6a6db366074d457f3 (patch) | |
tree | 34ef11e4eb14bc67c9dbe66f3ca16e427e4062e9 /source3/libsmb | |
parent | a5ba41881c393d075238a537aeca273df446389b (diff) | |
download | samba-1335059ff5ef1a8f0f9aedf6a6db366074d457f3.tar.gz samba-1335059ff5ef1a8f0f9aedf6a6db366074d457f3.tar.bz2 samba-1335059ff5ef1a8f0f9aedf6a6db366074d457f3.zip |
s3: Fix async smb handling
In cli_echo with more than one response we ended up with more than one read_smb
request. One from the call to cli_smb_req_set_pending called from
cli_smb_received. The other one from cli_smb_received itself. I don't really
see another way to deal with this than to hold the read_smb request in the
cli_state.
Metze, please check!
Volker
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/async_smb.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 87614bd326..ecc77803b0 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -139,6 +139,7 @@ void cli_smb_req_unset_pending(struct tevent_req *req) * delete the socket read fde. */ TALLOC_FREE(cli->conn.pending); + cli->conn.read_smb_req = NULL; return; } @@ -193,7 +194,6 @@ bool cli_smb_req_set_pending(struct tevent_req *req) struct cli_state *cli; struct tevent_req **pending; int num_pending; - struct tevent_req *subreq; cli = state->cli; num_pending = talloc_array_length(cli->conn.pending); @@ -207,7 +207,7 @@ bool cli_smb_req_set_pending(struct tevent_req *req) cli->conn.pending = pending; talloc_set_destructor(req, cli_smb_req_destructor); - if (num_pending > 0) { + if (cli->conn.read_smb_req != NULL) { return true; } @@ -215,12 +215,13 @@ bool cli_smb_req_set_pending(struct tevent_req *req) * We're the first ones, add the read_smb request that waits for the * answer from the server */ - subreq = read_smb_send(cli->conn.pending, state->ev, cli->conn.fd); - if (subreq == NULL) { + cli->conn.read_smb_req = read_smb_send(cli->conn.pending, state->ev, + cli->conn.fd); + if (cli->conn.read_smb_req == NULL) { cli_smb_req_unset_pending(req); return false; } - tevent_req_set_callback(subreq, cli_smb_received, cli); + tevent_req_set_callback(cli->conn.read_smb_req, cli_smb_received, cli); return true; } @@ -531,8 +532,16 @@ static void cli_smb_received(struct tevent_req *subreq) uint16_t mid; bool oplock_break; + if (subreq != cli->conn.read_smb_req) { + DEBUG(1, ("Internal error: cli_smb_received called with " + "unexpected subreq\n")); + status = NT_STATUS_INTERNAL_ERROR; + goto fail; + } + received = read_smb_recv(subreq, talloc_tos(), &inbuf, &err); TALLOC_FREE(subreq); + cli->conn.read_smb_req = NULL; if (received == -1) { cli_state_disconnect(cli); status = map_nt_error_from_unix(err); @@ -642,19 +651,22 @@ static void cli_smb_received(struct tevent_req *subreq) TALLOC_FREE(chain); } done: - if (talloc_array_length(cli->conn.pending) > 0) { + if ((talloc_array_length(cli->conn.pending) > 0) && + (cli->conn.read_smb_req == NULL)) { /* * Set up another read request for the other pending cli_smb * requests */ state = tevent_req_data(cli->conn.pending[0], struct cli_smb_state); - subreq = read_smb_send(cli->conn.pending, state->ev, cli->conn.fd); - if (subreq == NULL) { + cli->conn.read_smb_req = read_smb_send( + cli->conn.pending, state->ev, cli->conn.fd); + if (cli->conn.read_smb_req == NULL) { status = NT_STATUS_NO_MEMORY; goto fail; } - tevent_req_set_callback(subreq, cli_smb_received, cli); + tevent_req_set_callback(cli->conn.read_smb_req, + cli_smb_received, cli); } return; fail: |