title: gst-rtsp-server gst_rtsp_client_close
body: <p>I am using gst-rtsp-server and I want to be able to close an ongoing stream from the server. I am trying to use the <code>gst_rtsp_client_close()</code> function. However, when I call it the application sometimes becomes unresponsive. In the log I can see: <code>GLib-CRITICAL **: g_main_context_unref: assertion 'g_atomic_int_get (&amp;context-&gt;ref_count) &gt; 0' failed​</code>.</p>
  
  <p>I have modified the test-uri example to trigger this issue. Whenever a client connects, a timer will be started. When the timer runs out, <code>gst_rtsp_client_close()</code> will be called for that client.</p>
  
  <pre><code>/* GStreamer
   * Copyright (C) 2008 Wim Taymans &lt;wim.taymans at gmail.com&gt;
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Library General Public
   * License as published by the Free Software Foundation; either
   * version 2 of the License, or (at your option) any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Library General Public License for more details.
   *
   * You should have received a copy of the GNU Library General Public
   * License along with this library; if not, write to the
   * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
   * Boston, MA 02110-1301, USA.
   */
  
  #include &lt;gst/gst.h&gt;
  
  #include &lt;gst/rtsp-server/rtsp-server.h&gt;
  #include &lt;gst/rtsp-server/rtsp-media-factory-uri.h&gt;
  
  #define DEFAULT_RTSP_PORT "8554"
  
  static char *port = (char *) DEFAULT_RTSP_PORT;
  
  static GOptionEntry entries[] = {
    {"port", 'p', 0, G_OPTION_ARG_STRING, &amp;port,
        "Port to listen on (default: " DEFAULT_RTSP_PORT ")", "PORT"},
    {NULL}
  };
  
  static void
  client_closed(GstRTSPClient *client,
                gpointer user_data)
  {
    g_print("client closed %p\n", client);
  }
  
  static gboolean
  disconnect (GstRTSPClient * client)
  {
    g_print("disconnect client %p\n", client);
    gst_rtsp_client_close(client);
    return FALSE;
  }
  
  static void
  client_connected(GstRTSPServer *server,
                   GstRTSPClient *client,
                   gpointer user_data)
  {
    g_print("client connected %p\n", client);
    g_signal_connect(client, "closed", (GCallback)client_closed,
                     NULL);
    g_timeout_add_seconds (8, (GSourceFunc) disconnect, client);
  }
  
  int
  main (int argc, gchar * argv[])
  {
    GMainLoop *loop;
    GstRTSPServer *server;
    GstRTSPMountPoints *mounts;
    GstRTSPMediaFactoryURI *factory;
    GOptionContext *optctx;
    GError *error = NULL;
    gchar *uri;
  
  
    guint major;
    guint minor;
    guint micro;
    guint nano;
    gst_version(&amp;major, &amp;minor, &amp;micro, &amp;nano);
    g_print("%s started. GST version %u.%u.%u.%u\n", argv[0], major, minor, micro,     nano);
    optctx = g_option_context_new ("&lt;uri&gt; - Test RTSP Server, URI");
    g_option_context_add_main_entries (optctx, entries, NULL);
    g_option_context_add_group (optctx, gst_init_get_option_group ());
    if (!g_option_context_parse (optctx, &amp;argc, &amp;argv, &amp;error)) {
      g_printerr ("Error parsing options: %s\n", error-&gt;message);
      g_option_context_free (optctx);
      g_clear_error (&amp;error);
      return -1;
    }
    g_option_context_free (optctx);
  
    if (argc &lt; 2) {
      g_printerr ("Please pass an URI or file as argument!\n");
      return -1;
    }
  
    loop = g_main_loop_new (NULL, FALSE);
  
    /* create a server instance */
    server = gst_rtsp_server_new ();
    g_object_set (server, "service", port, NULL);
    g_signal_connect(server, "client-connected", (GCallback)client_connected,
                     NULL);
    /* get the mount points for this server, every server has a default object
     * that be used to map uri mount points to media factories */
    mounts = gst_rtsp_server_get_mount_points (server);
  
    /* make a URI media factory for a test stream. */
    factory = gst_rtsp_media_factory_uri_new ();
  
    /* check if URI is valid, otherwise convert filename to URI if it's a file */
    if (gst_uri_is_valid (argv[1])) {
      uri = g_strdup (argv[1]);
    } else if (g_file_test (argv[1], G_FILE_TEST_EXISTS)) {
      uri = gst_filename_to_uri (argv[1], NULL);
    } else {
      g_printerr ("Unrecognised command line argument '%s'.\n"
          "Please pass an URI or file as argument!\n", argv[1]);
      return -1;
    }
  
    gst_rtsp_media_factory_uri_set_uri (factory, uri);
    g_free (uri);
  
    /* attach the test factory to the /test url */
    gst_rtsp_mount_points_add_factory (mounts, "/test",
        GST_RTSP_MEDIA_FACTORY (factory));
  
    /* don't need the ref to the mapper anymore */
    g_object_unref (mounts);
  
    /* attach the server to the default maincontext */
    if (gst_rtsp_server_attach (server, NULL) == 0)
      goto failed;
  
    /* start serving */
    g_print ("stream ready at rtsp://127.0.0.1:%s/test\n", port);
    g_main_loop_run (loop);
  
    return 0;
  
    /* ERRORS */
  failed:
    {
      g_print ("failed to attach the server\n");
      return -1;
    }
  }
  </code></pre>
  
  <p>I start the application with: <code>./close-test-uri.out ~/Videos/big_buck_bunny.mp4</code>
  and then I connect to the RTSP stream using a client (VLC): <code>vlc -vvv "rtsp://127.0.0.1:8554/test"</code>
  The video will start playing and after 8 seconds it will (as expected), be disconnected. However, as mentioned before I get the critical error and the application becomes unresponsive (sometimes it crashes).</p>
  
  <p>Am I using <code>gst_rtsp_client_close()</code> it the wrong way?</p>
  
  <p>Thank you in advance!</p>