curl*sink: post error on bus in element, not transfer thread

https://bugzilla.gnome.org/show_bug.cgi?id=728960
This commit is contained in:
Sebastian Rasmussen 2014-04-15 23:53:32 +02:00 committed by Sebastian Dröge
parent 13f87a1db1
commit c75c7a9a53
7 changed files with 49 additions and 53 deletions

View file

@ -249,6 +249,7 @@ gst_curl_base_sink_init (GstCurlBaseSink * sink)
sink->url = g_strdup (DEFAULT_URL); sink->url = g_strdup (DEFAULT_URL);
sink->transfer_thread_close = FALSE; sink->transfer_thread_close = FALSE;
sink->new_file = TRUE; sink->new_file = TRUE;
sink->error = NULL;
sink->flow_ret = GST_FLOW_OK; sink->flow_ret = GST_FLOW_OK;
sink->is_live = FALSE; sink->is_live = FALSE;
} }
@ -338,16 +339,18 @@ gst_curl_base_sink_render (GstBaseSink * bsink, GstBuffer * buf)
guint8 *data; guint8 *data;
size_t size; size_t size;
GstFlowReturn ret; GstFlowReturn ret;
gchar *error;
GST_LOG ("enter render"); GST_LOG ("enter render");
sink = GST_CURL_BASE_SINK (bsink); sink = GST_CURL_BASE_SINK (bsink);
GST_OBJECT_LOCK (sink);
gst_buffer_map (buf, &map, GST_MAP_READ); gst_buffer_map (buf, &map, GST_MAP_READ);
data = map.data; data = map.data;
size = map.size; size = map.size;
GST_OBJECT_LOCK (sink);
/* check if the transfer thread has encountered problems while the /* check if the transfer thread has encountered problems while the
* pipeline thread was working elsewhere */ * pipeline thread was working elsewhere */
if (sink->flow_ret != GST_FLOW_OK) { if (sink->flow_ret != GST_FLOW_OK) {
@ -376,9 +379,19 @@ gst_curl_base_sink_render (GstBaseSink * bsink, GstBuffer * buf)
gst_curl_base_sink_wait_for_transfer_thread_to_send_unlocked (sink); gst_curl_base_sink_wait_for_transfer_thread_to_send_unlocked (sink);
done: done:
gst_buffer_unmap (buf, &map);
/* Hand over error from transfer thread to streaming thread */
error = sink->error;
sink->error = NULL;
ret = sink->flow_ret; ret = sink->flow_ret;
GST_OBJECT_UNLOCK (sink); GST_OBJECT_UNLOCK (sink);
gst_buffer_unmap (buf, &map);
if (error != NULL) {
GST_ERROR_OBJECT (sink, "%s", error);
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, ("%s", error), (NULL));
g_free (error);
}
GST_LOG ("exit render"); GST_LOG ("exit render");
@ -841,14 +854,13 @@ handle_transfer (GstCurlBaseSink * sink)
goto fail; goto fail;
} else { } else {
GST_DEBUG_OBJECT (sink, "poll failed: %s", g_strerror (errno)); sink->error = g_strdup_printf ("poll failed: %s", g_strerror (errno));
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, ("poll failed"), (NULL));
retval = GST_FLOW_ERROR; retval = GST_FLOW_ERROR;
goto fail; goto fail;
} }
} else if (G_UNLIKELY (activated_fds == 0)) { } else if (G_UNLIKELY (activated_fds == 0)) {
GST_DEBUG_OBJECT (sink, "poll timed out"); sink->error = g_strdup_printf ("poll timed out after %" GST_TIME_FORMAT,
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, ("poll timed out"), (NULL)); GST_TIME_ARGS (timeout * GST_SECOND));
retval = GST_FLOW_ERROR; retval = GST_FLOW_ERROR;
goto fail; goto fail;
} }
@ -860,9 +872,8 @@ handle_transfer (GstCurlBaseSink * sink)
} }
if (m_code != CURLM_OK) { if (m_code != CURLM_OK) {
GST_DEBUG_OBJECT (sink, "curl multi error"); sink->error = g_strdup_printf ("failed to write data: %s",
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, ("%s", curl_multi_strerror (m_code));
curl_multi_strerror (m_code)), (NULL));
retval = GST_FLOW_ERROR; retval = GST_FLOW_ERROR;
goto fail; goto fail;
} }
@ -870,9 +881,8 @@ handle_transfer (GstCurlBaseSink * sink)
/* problems still might have occurred on individual transfers even when /* problems still might have occurred on individual transfers even when
* curl_multi_perform returns CURLM_OK */ * curl_multi_perform returns CURLM_OK */
if ((e_code = gst_curl_base_sink_transfer_check (sink)) != CURLE_OK) { if ((e_code = gst_curl_base_sink_transfer_check (sink)) != CURLE_OK) {
GST_DEBUG_OBJECT (sink, "curl easy error"); sink->error = g_strdup_printf ("failed to transfer data: %s",
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, ("%s", curl_easy_strerror (e_code));
curl_easy_strerror (e_code)), (NULL));
retval = GST_FLOW_ERROR; retval = GST_FLOW_ERROR;
goto fail; goto fail;
} }
@ -966,8 +976,7 @@ gst_curl_base_sink_transfer_thread_func (gpointer data)
GST_LOG ("transfer thread started"); GST_LOG ("transfer thread started");
GST_OBJECT_LOCK (sink); GST_OBJECT_LOCK (sink);
if (!gst_curl_base_sink_transfer_setup_unlocked (sink)) { if (!gst_curl_base_sink_transfer_setup_unlocked (sink)) {
GST_DEBUG_OBJECT (sink, "curl setup error"); /* no need to set sink->error, as it is set by the called function */
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, ("curl setup error"), (NULL));
sink->flow_ret = GST_FLOW_ERROR; sink->flow_ret = GST_FLOW_ERROR;
goto done; goto done;
} }
@ -983,11 +992,8 @@ gst_curl_base_sink_transfer_thread_func (gpointer data)
data_available = gst_curl_base_sink_wait_for_data_unlocked (sink); data_available = gst_curl_base_sink_wait_for_data_unlocked (sink);
if (data_available) { if (data_available) {
if (G_UNLIKELY (!klass->set_protocol_dynamic_options_unlocked (sink))) { if (G_UNLIKELY (!klass->set_protocol_dynamic_options_unlocked (sink))) {
sink->error = g_strdup ("unexpected state");
sink->flow_ret = GST_FLOW_ERROR; sink->flow_ret = GST_FLOW_ERROR;
GST_OBJECT_UNLOCK (sink);
GST_ELEMENT_ERROR (sink, RESOURCE, FAILED, ("Unexpected state."),
(NULL));
GST_OBJECT_LOCK (sink);
goto done; goto done;
} }
} }
@ -1057,20 +1063,20 @@ gst_curl_base_sink_transfer_setup_unlocked (GstCurlBaseSink * sink)
if (sink->curl == NULL) { if (sink->curl == NULL) {
/* curl_easy_init automatically calls curl_global_init(3) */ /* curl_easy_init automatically calls curl_global_init(3) */
if ((sink->curl = curl_easy_init ()) == NULL) { if ((sink->curl = curl_easy_init ()) == NULL) {
g_warning ("Failed to init easy handle"); sink->error = g_strdup ("failed to init curl easy handle");
return FALSE; return FALSE;
} }
} }
if (!gst_curl_base_sink_transfer_set_options_unlocked (sink)) { if (!gst_curl_base_sink_transfer_set_options_unlocked (sink)) {
g_warning ("Failed to setup easy handle"); sink->error = g_strdup ("failed to setup curl easy handle");
GST_OBJECT_UNLOCK (sink);
return FALSE; return FALSE;
} }
/* init a multi stack (non-blocking interface to libcurl) */ /* init a multi stack (non-blocking interface to libcurl) */
if (sink->multi_handle == NULL) { if (sink->multi_handle == NULL) {
if ((sink->multi_handle = curl_multi_init ()) == NULL) { if ((sink->multi_handle = curl_multi_init ()) == NULL) {
sink->error = g_strdup ("failed to init curl multi handle");
return FALSE; return FALSE;
} }
} }

View file

@ -68,6 +68,7 @@ struct _GstCurlBaseSink
GstPollFD fd; GstPollFD fd;
GstPoll *fdset; GstPoll *fdset;
GThread *transfer_thread; GThread *transfer_thread;
gchar *error;
GstFlowReturn flow_ret; GstFlowReturn flow_ret;
TransferBuffer *transfer_buf; TransferBuffer *transfer_buf;
TransferCondition *transfer_cond; TransferCondition *transfer_cond;

View file

@ -213,9 +213,7 @@ gst_curl_file_sink_prepare_transfer (GstCurlBaseSink * basesink)
gchar *url = g_strdup_printf ("%s%s", basesink->url, basesink->file_name); gchar *url = g_strdup_printf ("%s%s", basesink->url, basesink->file_name);
file_name = g_filename_from_uri (url, NULL, NULL); file_name = g_filename_from_uri (url, NULL, NULL);
if (file_name == NULL) { if (file_name == NULL) {
GST_DEBUG_OBJECT (sink, "failed to parse file name of '%s'", url); basesink->error = g_strdup_printf ("failed to parse file name '%s'", url);
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, ("failed to parse file name"),
(NULL));
g_free (url); g_free (url);
return FALSE; return FALSE;
} }
@ -226,9 +224,8 @@ gst_curl_file_sink_prepare_transfer (GstCurlBaseSink * basesink)
/* create dir if file name contains dir component */ /* create dir if file name contains dir component */
gchar *dir_name = g_strndup (file_name, last_slash - file_name); gchar *dir_name = g_strndup (file_name, last_slash - file_name);
if (g_mkdir_with_parents (dir_name, S_IRWXU) < 0) { if (g_mkdir_with_parents (dir_name, S_IRWXU) < 0) {
GST_DEBUG_OBJECT (sink, "failed to create directory '%s'", dir_name); basesink->error = g_strdup_printf ("failed to create directory '%s'",
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, dir_name);
("failed to create directory"), (NULL));
g_free (file_name); g_free (file_name);
g_free (dir_name); g_free (dir_name);
return FALSE; return FALSE;

View file

@ -249,12 +249,8 @@ set_ftp_options_unlocked (GstCurlBaseSink * basesink)
sink->ftp_port_arg); sink->ftp_port_arg);
if (res != CURLE_OK) { if (res != CURLE_OK) {
GST_DEBUG_OBJECT (sink, "Failed to set up active mode: %s", basesink->error = g_strdup_printf ("failed to set up active mode: %s",
curl_easy_strerror (res)); curl_easy_strerror (res));
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
("Failed to set up active mode: %s", curl_easy_strerror (res)),
(NULL));
return FALSE; return FALSE;
} }

View file

@ -397,9 +397,8 @@ gst_curl_http_sink_transfer_verify_response_code (GstCurlBaseSink * bcsink)
GST_DEBUG_OBJECT (sink, "response code: %ld", resp); GST_DEBUG_OBJECT (sink, "response code: %ld", resp);
if (resp < 100 || resp >= 300) { if (resp < 100 || resp >= 300) {
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, bcsink->error = g_strdup_printf ("HTTP response error: (received: %ld)",
("HTTP response error: (received: %ld)", resp), (NULL)); resp);
return FALSE; return FALSE;
} }

View file

@ -137,13 +137,14 @@ gst_curl_sftp_sink_finalize (GObject * gobject)
static gboolean static gboolean
set_sftp_dynamic_options_unlocked (GstCurlBaseSink * basesink) set_sftp_dynamic_options_unlocked (GstCurlBaseSink * basesink)
{ {
GstCurlSftpSink *sink = GST_CURL_SFTP_SINK (basesink);
gchar *tmp = g_strdup_printf ("%s%s", basesink->url, basesink->file_name); gchar *tmp = g_strdup_printf ("%s%s", basesink->url, basesink->file_name);
gint curl_err = CURLE_OK; CURLcode curl_err = CURLE_OK;
if ((curl_err = if ((curl_err =
curl_easy_setopt (basesink->curl, CURLOPT_URL, tmp)) != CURLE_OK) { curl_easy_setopt (basesink->curl, CURLOPT_URL, tmp)) != CURLE_OK) {
GST_ERROR_OBJECT (sink, "curl error: %d setting URL to: %s", curl_err, tmp); basesink->error = g_strdup_printf ("failed to set URL: %s",
curl_easy_strerror (curl_err));
return FALSE;
} }
g_free (tmp); g_free (tmp);
@ -156,19 +157,22 @@ set_sftp_options_unlocked (GstCurlBaseSink * basesink)
{ {
GstCurlSftpSink *sink = GST_CURL_SFTP_SINK (basesink); GstCurlSftpSink *sink = GST_CURL_SFTP_SINK (basesink);
GstCurlSshSinkClass *parent_class; GstCurlSshSinkClass *parent_class;
gint curl_err = CURLE_OK; CURLcode curl_err = CURLE_OK;
if ((curl_err = if ((curl_err =
curl_easy_setopt (basesink->curl, CURLOPT_UPLOAD, 1L)) != CURLE_OK) { curl_easy_setopt (basesink->curl, CURLOPT_UPLOAD, 1L)) != CURLE_OK) {
GST_ERROR_OBJECT (sink, "curl error: %d setting CURLOPT_UPLOAD to 1", basesink->error = g_strdup_printf ("failed to prepare for upload: %s",
curl_err); curl_easy_strerror (curl_err));
return FALSE;
} }
if (sink->create_dirs) { if (sink->create_dirs) {
if ((curl_err = curl_easy_setopt (basesink->curl, if ((curl_err = curl_easy_setopt (basesink->curl,
CURLOPT_FTP_CREATE_MISSING_DIRS, 1L)) != CURLE_OK) { CURLOPT_FTP_CREATE_MISSING_DIRS, 1L)) != CURLE_OK) {
GST_ERROR_OBJECT (sink, basesink->error =
"curl error: %d setting FTP_CREATE_MISSING_DIRS to 1", curl_err); g_strdup_printf ("failed to set create missing dirs: %s",
curl_easy_strerror (curl_err));
return FALSE;
} }
} }

View file

@ -941,7 +941,6 @@ transfer_payload_headers (GstCurlSmtpSink * sink,
return bytes_to_send; return bytes_to_send;
} }
static gboolean static gboolean
gst_curl_smtp_sink_prepare_transfer (GstCurlBaseSink * bcsink) gst_curl_smtp_sink_prepare_transfer (GstCurlBaseSink * bcsink)
{ {
@ -951,10 +950,7 @@ gst_curl_smtp_sink_prepare_transfer (GstCurlBaseSink * bcsink)
if (sink->pop_location && strlen (sink->pop_location)) { if (sink->pop_location && strlen (sink->pop_location)) {
if ((sink->pop_curl = curl_easy_init ()) == NULL) { if ((sink->pop_curl = curl_easy_init ()) == NULL) {
GST_DEBUG_OBJECT (sink, "POP protocol: failed to create handler"); bcsink->error = g_strdup ("POP protocol: failed to create handler");
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
("POP protocol: failed to create handler"), (NULL));
return FALSE; return FALSE;
} }
@ -973,11 +969,8 @@ gst_curl_smtp_sink_prepare_transfer (GstCurlBaseSink * bcsink)
/* ready to initialize connection to POP server */ /* ready to initialize connection to POP server */
res = curl_easy_perform (sink->pop_curl); res = curl_easy_perform (sink->pop_curl);
if (res != CURLE_OK) { if (res != CURLE_OK) {
GST_DEBUG_OBJECT (sink, "POP transfer failed: %s", bcsink->error = g_strdup_printf ("POP transfer failed: %s",
curl_easy_strerror (res)); curl_easy_strerror (res));
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, ("POP transfer failed: %s",
curl_easy_strerror (res)), (NULL));
ret = FALSE; ret = FALSE;
} }