[vlc-devel] [PATCH] smb2: fix teardown when interrupted

Thomas Guillem thomas at gllm.fr
Thu Aug 8 15:00:43 CEST 2019


When the input is stopped by the user, there are lot of chances that this
access is waiting for the read command completion (smb2_read_async()).

If the read command is not fully processed (since interrupted by VLC), any
future commands will fail, like smb2_close_async() when the access is finally
closed.

To fix this issue, we switch back to the posix poll() when interrupted to let a
chance to finish the current command in order to be able to close the smb2
session nicely.
---
 modules/access/smb2.c | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/modules/access/smb2.c b/modules/access/smb2.c
index 66adc28fa3..5cdbf209b4 100644
--- a/modules/access/smb2.c
+++ b/modules/access/smb2.c
@@ -135,17 +135,20 @@ smb2_set_generic_error(stream_t *access, const char *psz_func)
 static int
 vlc_smb2_mainloop(stream_t *access, bool teardown)
 {
+#define TEARDOWN_TIMEOUT 250 /* in ms */
     struct access_sys *sys = access->p_sys;
 
     int timeout = -1;
     int (*poll_func)(struct pollfd *, unsigned, int) = vlc_poll_i11e;
 
-    if (teardown && vlc_killed())
+    if (teardown)
     {
-        /* The thread is interrupted, so vlc_poll_i11e will return immediatly.
-         * Use poll() with a timeout instead for tear down. */
-        timeout = 500;
+        /* Don't use vlc_poll_i11e that will return immediately with the EINTR
+         * errno if VLC's input is interrupted. Use the posix poll with a
+         * timeout to let a chance for a clean teardown. */
+        timeout = TEARDOWN_TIMEOUT;
         poll_func = (void *)poll;
+        sys->error_status = 0;
     }
 
     sys->res_done = false;
@@ -159,11 +162,27 @@ vlc_smb2_mainloop(stream_t *access, bool teardown)
         if (p_fds[0].fd == -1 || (ret = poll_func(p_fds, 1, timeout)) < 0)
         {
             if (errno == EINTR)
+            {
                 msg_Warn(access, "vlc_poll_i11e interrupted");
+                if (poll_func != (void *) poll)
+                {
+                    /* Try again with a timeout to let the command complete.
+                     * Indeed, if this command is interrupted, every future
+                     * commands will fail and we won't be able to teardown. */
+                    timeout = TEARDOWN_TIMEOUT;
+                    poll_func = (void *) poll;
+                }
+                else
+                    sys->error_status = -errno;
+            }
             else
+            {
                 msg_Err(access, "vlc_poll_i11e failed");
-            sys->error_status = -errno;
+                sys->error_status = -errno;
+            }
         }
+        else if (ret == 0)
+            sys->error_status = -ETIMEDOUT;
         else if (ret > 0 && p_fds[0].revents
              && smb2_service(sys->smb2, p_fds[0].revents) < 0)
             VLC_SMB2_SET_GENERIC_ERROR(access, "smb2_service");
-- 
2.20.1



More information about the vlc-devel mailing list