This is a pretty interesting one ! In the SMB1 case, if a writev fails we notive inside libcli/smb/smbXcli_base.c:smb1cli_req_writev_done() when nwritten = writev_recv(subreq, &err); comes back as -1. We then call: if (nwritten == -1) { NTSTATUS status = map_nt_error_from_unix_common(err); smbXcli_conn_disconnect(state->conn, status); smbXcli_conn_disconnect() calls tevent_req_nterror(req, status) on all the reqs on the pending queue. However, in the SMB1 case - because we can have one way writes, we don't add the req onto the pending queue until *after* the writev_recv() completed *successfully*. We can see this in the original code for smb1cli_req_writev_done(), which looks like: -------------------------------------------------------------------------- static void smb1cli_req_writev_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct smbXcli_req_state *state = tevent_req_data(req, struct smbXcli_req_state); ssize_t nwritten; int err; nwritten = writev_recv(subreq, &err); TALLOC_FREE(subreq); if (nwritten == -1) { NTSTATUS status = map_nt_error_from_unix_common(err); smbXcli_conn_disconnect(state->conn, status); return; } if (state->one_way) { state->inbuf = NULL; tevent_req_done(req); return; } if (!smbXcli_req_set_pending(req)) { tevent_req_nterror(req, NT_STATUS_NO_MEMORY); return; } } -------------------------------------------------------------------------- Note how smbXcli_req_set_pending(req) isn't called until *after* we would have returned early if nwritten == -1. So the call to smbXcli_conn_disconnect() in this case doesn't cancel the current outstanding tevent req, and so it's left on the event queue until it times out with the default timeout of 20 seconds. The solution is a patch which adds a: tevent_req_nterror(req, status); just after the call to smbXcli_conn_disconnect(state->conn, status) and so correctly cancels the current request. Note this isn't needed in any other calls that use smbXcli_conn_disconnect() on error, as they are either SMB1 reads (which by definition already have the original sender on the pending queue) or are SMB2 requests - and in the SMB2 code path we add the tevent req's to the pending queue *before* we do the writev_send - there are no one-way sends in SMB2. Patch has been tested in bug 11079, which is where this behavior was first seen. https://bugzilla.samba.org/show_bug.cgi?id=11079
Created attachment 10892 [details] git-am fix for master.
Comment on attachment 10892 [details] git-am fix for master. FYI: Fix confirmed by reporter in bug report: https://bugzilla.samba.org/show_bug.cgi?id=11079
Created attachment 10897 [details] git-am fix for 4.2.next, 4.1.next. Cherry-pick from master. Applies cleanly to 4.2.next, 4.1.next.
@Karolin, please merge to the maintenance branches.
Pushed to autobuild-v4-[1|2]-test.
(In reply to Karolin Seeger from comment #5) Pushed to bith branches. Closing out bug report. Thanks!