Просмотр исходного кода

obs-outputs: Implement send timeout in librtmp

This fixes a bug where the RTMP send thread can deadlock upon the
underlying TCP connection being broken. By introducing a send timeout,
this allows the thread to unblock and give up, triggering a reconnect
as normal. The correct solution to this problem would be to rewrite
librtmp with asynchronous IO, but that seems like something unlikely
to happen.

**Before**:
- Start stream in OBS
- Use tool (pfSense) to invalidate connection state
- OBS bitrate drops to 0
- Output does not respond to stop signals, and hangs for an undefined
amount of time (usually multiple minutes) before finally giving up

**After**:
- Start stream in OBS
- Use tool (pfSense) to invalidate connection state
- OBS bitrate drops to 0
- Output sits in blocked state for maximum of 8 seconds, then cleans
up and triggers the reconnect logic
tt2468 3 лет назад
Родитель
Сommit
66a7db7f2a
2 измененных файлов с 16 добавлено и 6 удалено
  1. 14 5
      plugins/obs-outputs/librtmp/rtmp.c
  2. 2 1
      plugins/obs-outputs/librtmp/rtmp.h

+ 14 - 5
plugins/obs-outputs/librtmp/rtmp.c

@@ -484,7 +484,8 @@ RTMP_Reset(RTMP *r)
     r->m_fVideoCodecs = 252.0;
     r->Link.curStreamIdx = 0;
     r->Link.nStreams = 0;
-    r->Link.timeout = 30;
+    r->Link.receiveTimeout = 30;
+    r->Link.sendTimeout = 6;
     r->Link.swfAge = 30;
 }
 
@@ -928,12 +929,20 @@ RTMP_Connect0(RTMP *r, struct sockaddr * service, socklen_t addrlen)
 
     /* set timeout */
     {
-        SET_RCVTIMEO(tv, r->Link.timeout);
+        SET_RCVTIMEO(tvr, r->Link.receiveTimeout);
         if (setsockopt
-                (r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)))
+                (r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tvr, sizeof(tvr)))
         {
-            RTMP_Log(RTMP_LOGERROR, "%s, Setting socket timeout to %ds failed!",
-                     __FUNCTION__, r->Link.timeout);
+            RTMP_Log(RTMP_LOGERROR, "%s, Setting socket receive timeout to %ds failed!",
+                     __FUNCTION__, r->Link.receiveTimeout);
+        }
+
+        SET_RCVTIMEO(tvs, r->Link.sendTimeout);
+        if (setsockopt
+                (r->m_sb.sb_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tvs, sizeof(tvs)))
+        {
+                RTMP_Log(RTMP_LOGERROR, "%s, Setting socket send timeout to %ds failed!",
+                     __FUNCTION__, r->Link.sendTimeout);
         }
     }
 

+ 2 - 1
plugins/obs-outputs/librtmp/rtmp.h

@@ -328,7 +328,8 @@ extern "C"
         int swfAge;
 
         int protocol;
-        int timeout;		/* connection timeout in seconds */
+        int receiveTimeout;	/* connection receive timeout in seconds */
+        int sendTimeout;	/* connection send timeout in seconds */
 
 #define RTMP_PUB_NAME   0x0001  /* send login to server */
 #define RTMP_PUB_RESP   0x0002  /* send salted password hash */