OpenVidu / openvidu

OpenVidu Platform main repository
https://openvidu.io
Apache License 2.0
1.88k stars 464 forks source link

[openvidu-server] Unexpectedly java.lang.NullPointerException when start to record a session #527

Open brunobottazzini opened 4 years ago

brunobottazzini commented 4 years ago

Describe the bug java.lang.NullPointerException when starting a record right after the user has forcefully quit the conference.

In other words:

openvidu-server respond us with HTTP response code 500 and NullPointerException can be found in its log.

[ERROR] 2020-08-26 12:41:20,419 [-4443-exec-1] org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] (log) - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
    at io.openvidu.server.recording.service.SingleStreamRecordingService.sealMetadataFiles(SingleStreamRecordingService.java:360)
    at io.openvidu.server.recording.service.SingleStreamRecordingService.stopRecording(SingleStreamRecordingService.java:161)
    at io.openvidu.server.recording.service.SingleStreamRecordingService.stopRecording(SingleStreamRecordingService.java:132)
    at io.openvidu.server.recording.service.RecordingService.failStartRecording(RecordingService.java:167)
    at io.openvidu.server.recording.service.SingleStreamRecordingService.startRecording(SingleStreamRecordingService.java:116)
    at io.openvidu.server.recording.service.RecordingManager.startRecording(RecordingManager.java:184)
    at io.openvidu.server.rest.SessionRestController.startRecordingSession(SessionRestController.java:497)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:220)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

2020-08-26 14:41:30,178 DEBG 'openvidu-server' stdout output:
[INFO] 2020-08-26 12:41:30,177 [-4443-exec-6] io.openvidu.server.rest.SessionRestController (listSessions) - REST API: GET /api/sessions

2020-08-26 14:41:40,176 DEBG 'openvidu-server' stdout output:
[INFO] 2020-08-26 12:41:40,176 [4443-exec-10] io.openvidu.server.rest.SessionRestController (listSessions) - REST API: GET /api/sessions

2020-08-26 14:41:45,952 DEBG 'kms' stdout output:
5:03:01.372452189     8 0x7f89e8001300 INFO    KurentoWebSocketTransport WebSocketTransport.cpp:263:keepAliveSessions: Keep alive c31d5ad4-f0d3-48f8-ac82-03467f4664cf

2020-08-26 14:41:48,691 DEBG 'openvidu-server' stdout output:
[INFO] 2020-08-26 12:41:48,690 [drq0u-e29-t0] io.openvidu.server.rpc.RpcHandler (sanityCheckOfSession) - Participant bi5fvzep4nhe6vbs is calling method 'unsubscribe' in session 5f4624022a60dc6522722c49

2020-08-26 14:41:48,691 DEBG 'openvidu-server' stdout output:
[WARN] 2020-08-26 12:41:48,690 [drq0u-e29-t0] io.openvidu.server.kurento.core.KurentoSessionManager (unsubscribe) - PARTICIPANT bi5fvzep4nhe6vbs: Requesting to unsubscribe from user qf0l5hgce2024uvv in session 5f4624022a60dc6522722c49 but user could not be found
[ERROR] 2020-08-26 12:41:48,691 [drq0u-e29-t0] org.kurento.jsonrpc.internal.JsonRpcHandlerManager (handleRequest) - Exception while processing request {"id":91,"method":"unsubscribeFromVideo","params":{"sender":"qf0l5hgce2024uvv"},"jsonrpc":"2.0"}
io.openvidu.client.OpenViduException: User qf0l5hgce2024uvv not found in session 5f4624022a60dc6522722c49. Code: 102
    at io.openvidu.server.kurento.core.KurentoSessionManager.unsubscribe(KurentoSessionManager.java:422)
    at io.openvidu.server.rpc.RpcHandler.unsubscribeFromVideo(RpcHandler.java:328)
    at io.openvidu.server.rpc.RpcHandler.handleRequest(RpcHandler.java:132)
    at org.kurento.jsonrpc.internal.JsonRpcHandlerManager.handleRequest(JsonRpcHandlerManager.java:128)
    at org.kurento.jsonrpc.internal.server.ProtocolManager$3.run(ProtocolManager.java:218)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

Expected behavior When calling openvidu server via rest template with POST the server should respond us with a meaningful response code or a message explaining why the record could not start. As shown the response code in the documentation.

Maybe it could ignore the "unreachable" users and start recording people who is reachable in the session at the moment?

Wrong current behavior The server is giving us a non predicted HTTP Response code: 500 as you can see it is not mapped in the documentation.

Or maybe as written above, it might not give us an error at all.

OpenVidu tutorial where to replicate the error Tried to replicate the problem using openvidu-recording-java but I could not start a record at all to see if it happens also in the tutorials. I think there are some missing information to use it, Am I missing any configuration?

docker run -p 4443:4443 --rm -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp -e openvidu.recording=true -e openvidu.recording.path=/tmp openvidu/openvidu-server-kms:2.15.0

Schermata da 2020-08-27 11-05-49

Schermata da 2020-08-27 11-06-09

OpenVidu deployment info How is your OpenVidu Server instance deployed when you get the bug. A couple of possible examples are listed below:

docker run --name my-openvidu \
--user "0:$GID" \
        -d --network=networktest \
        -p 4443:4443 \                                                                                                                                                                                          
        -e openvidu.secret=$OPENVIDU_SECRET \
        -e openvidu.cdr=true \
        -e openvidu.recording=true \
        -e server.ssl.enabled=false \
        -e "openvidu.publicurl=$PUBLICURL" \
        -e openvidu.webhook=true \
        -e openvidu.webhook.endpoint=http://endpoint:8080/server/api/logs/rpclog \
        -e openvidu.webhook.headers=  \
        -e "openvidu.webhook.events=[messageSent,participantJoined,participantLeft]" \
        -e openvidu.recording.path=/opt/openvidu/recordings \
        -e "KMS_STUN_IP=$PUBLICIP" -e KMS_STUN_PORT=$KMS_STUN_PORT \
        -e "KMS_TURN_URL=$KMS_TURN_URL" \
        -v /usr/share/zoneinfo/Europe/Rome:/etc/localtime \
        -v $VIDEOPATH:/opt/openvidu/recordings \
        -v "$OPENVIDU_LOGS/supervisor:/var/log/supervisor" \
        -v "$OPENVIDU_LOGS/cdr:/log" \
        -v /var/run/docker.sock:/var/run/docker.sock \
        -v "$LIBS/openvidu-server-2.9.1-EM.jar:/openvidu-server.jar:ro" \
        openvidu/openvidu-server-kms:2.9.0

IMPORTANT NOTE: please, if you think the bug might be related to OpenVidu Server side, specify here if you are also getting the error by using OpenVidu Server Demos instance. This instance is publicly available (use it only for this test, because it is not secure!!!): URL: https://demos.openvidu.io:4443, SECRET: MY_SECRET

Could not find a way to test a record inside demos.openvidu.io

Client device info (if applicable) Describe the client device(s) or platform(s) where you are able to replicate the error. For example:

pabloFuente commented 4 years ago

Hello,

Can you please try to replicate this issue with openvidu-server-kms Docker container and the openvidu-recording-java tutorial? I see that you tried, but your docker run command wasn't valid. Try this one:

docker run -p 4443:4443 --rm \
    -e OPENVIDU_RECORDING=true \
    -e OPENVIDU_RECORDING_PATH=/opt/openvidu/recordings \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /opt/openvidu/recordings:/opt/openvidu/recordings \
openvidu/openvidu-server-kms:2.15.0

(The recording path in this command is set to /opt/openvidu/recordings)

If you are able to replicate the issue with this set up, we will be able to fix it very quickly if there's in fact a problem. Thank you.

brunobottazzini commented 4 years ago

Hello,

Thank you very much for the information. I could replicate the problem in question using the tutorials.

Steps:

  1. Configure Openvidu to expose my local ip address and start openvidu-server
  2. Start the tutorial openvidu-recording-java
  3. Open Chrome or Firefox in my PC and enter SessionA
  4. With my Cellphone with chrome opened. Enter the SessionA
  5. Close my cellphone browser
  6. in my PC click start record with the following parameters: {"session":"ses_L5JoKqYUUe","outputMode":"INDIVIDUAL","hasAudio":true,"hasVideo":true}

The behavior: The POST call hangs for about 10 seconds. Schermata da 2020-08-27 13-02-25

The response: Schermata da 2020-08-27 13-01-35

The application: Schermata da 2020-08-27 12-57-46

hsxhsx commented 4 years ago

I used Docker to deploy the whole service normally, now I'm using your source code to develop OpenVidu-Server, the recording module is problematic. Recording alone with a REST-API call results are fine, but the generated ZIP file unzips only one JSON, which has been bothering me for a long time. Please help to check, thank you

hsxhsx commented 4 years ago

I used Docker to deploy the whole service normally, now I'm using your source code to develop OpenVidu-Server, the recording module is problematic. Recording alone with a REST-API call results are fine, but the generated ZIP file unzips only one JSON, which has been bothering me for a long time. Please help to check, thank you

截屏2020-09-1110 10 37 截屏2020-09-1110 10 49
Vellore-yamini1 commented 3 years ago

Hello,

Is any one worked on screen sharing and recording using Openvidu in iOS mobile application. if YES, please let me know the process.