mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
plugins/elements/gstfdsink.c: handle EAGAIN, EINTR and short writes correctly. Also clean up some error cases, avoid ...
Original commit message from CVS: * plugins/elements/gstfdsink.c: (gst_fd_sink_render), (gst_fd_sink_check_fd), (gst_fd_sink_update_fd): handle EAGAIN, EINTR and short writes correctly. Also clean up some error cases, avoid a deadlock on bad file descriptors and use GST_DEBUG_OBJECT. Fixes #339843
This commit is contained in:
parent
1089154f2a
commit
09eeb714c2
2 changed files with 69 additions and 26 deletions
|
@ -1,3 +1,12 @@
|
||||||
|
2006-04-28 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* plugins/elements/gstfdsink.c: (gst_fd_sink_render),
|
||||||
|
(gst_fd_sink_check_fd), (gst_fd_sink_update_fd):
|
||||||
|
handle EAGAIN, EINTR and short writes correctly. Also clean
|
||||||
|
up some error cases, avoid a deadlock on bad file descriptors and
|
||||||
|
use GST_DEBUG_OBJECT.
|
||||||
|
Fixes #339843
|
||||||
|
|
||||||
2006-04-28 Wim Taymans <wim@fluendo.com>
|
2006-04-28 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst/gstvalue.c: (gst_value_serialize_buffer),
|
* gst/gstvalue.c: (gst_value_serialize_buffer),
|
||||||
|
|
|
@ -26,6 +26,12 @@
|
||||||
* @see_also: #GstFdSrc
|
* @see_also: #GstFdSrc
|
||||||
*
|
*
|
||||||
* Write data to a unix file descriptor.
|
* Write data to a unix file descriptor.
|
||||||
|
*
|
||||||
|
* This element will sycnhronize on the clock before writing the data on the
|
||||||
|
* socket. For file descriptors where this does not make sense (files, ...) the
|
||||||
|
* ::sync property can be used to disable synchronisation.
|
||||||
|
*
|
||||||
|
* Last reviewed on 2006-04-28 (0.10.6)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
|
@ -237,12 +243,20 @@ gst_fd_sink_render (GstBaseSink * sink, GstBuffer * buffer)
|
||||||
fd_set writefds;
|
fd_set writefds;
|
||||||
gint retval;
|
gint retval;
|
||||||
#endif
|
#endif
|
||||||
|
guint8 *data;
|
||||||
|
guint size;
|
||||||
|
gint written;
|
||||||
|
|
||||||
fdsink = GST_FD_SINK (sink);
|
fdsink = GST_FD_SINK (sink);
|
||||||
|
|
||||||
g_return_val_if_fail (fdsink->fd >= 0, GST_FLOW_ERROR);
|
g_return_val_if_fail (fdsink->fd >= 0, GST_FLOW_ERROR);
|
||||||
|
|
||||||
|
data = GST_BUFFER_DATA (buffer);
|
||||||
|
size = GST_BUFFER_SIZE (buffer);
|
||||||
|
|
||||||
|
again:
|
||||||
#ifndef HAVE_WIN32
|
#ifndef HAVE_WIN32
|
||||||
|
|
||||||
FD_ZERO (&readfds);
|
FD_ZERO (&readfds);
|
||||||
FD_SET (READ_SOCKET (fdsink), &readfds);
|
FD_SET (READ_SOCKET (fdsink), &readfds);
|
||||||
|
|
||||||
|
@ -250,6 +264,8 @@ gst_fd_sink_render (GstBaseSink * sink, GstBuffer * buffer)
|
||||||
FD_SET (fdsink->fd, &writefds);
|
FD_SET (fdsink->fd, &writefds);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
GST_DEBUG_OBJECT (fdsink, "going into select, have %d bytes to write",
|
||||||
|
size);
|
||||||
retval = select (FD_SETSIZE, &readfds, &writefds, NULL, NULL);
|
retval = select (FD_SETSIZE, &readfds, &writefds, NULL, NULL);
|
||||||
} while ((retval == -1 && errno == EINTR));
|
} while ((retval == -1 && errno == EINTR));
|
||||||
|
|
||||||
|
@ -273,20 +289,32 @@ gst_fd_sink_render (GstBaseSink * sink, GstBuffer * buffer)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (GST_BUFFER_DATA (buffer)) {
|
GST_DEBUG_OBJECT (fdsink, "writing %d bytes to file descriptor %d", size,
|
||||||
guint bytes_written;
|
fdsink->fd);
|
||||||
|
|
||||||
GST_DEBUG ("writing %d bytes to file descriptor %d",
|
written = write (fdsink->fd, data, size);
|
||||||
GST_BUFFER_SIZE (buffer), fdsink->fd);
|
|
||||||
/* FIXME: short writes are perfectly valid and may happen; also,
|
/* check for errors */
|
||||||
* we should probably handle EINTR and EAGAIN in a non-fatal way */
|
if (G_UNLIKELY (written < 0)) {
|
||||||
bytes_written =
|
/* try to write again on non-fatal errors */
|
||||||
write (fdsink->fd, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
|
if (errno == EAGAIN || errno == EINTR)
|
||||||
fdsink->bytes_written += bytes_written;
|
goto again;
|
||||||
if (bytes_written != GST_BUFFER_SIZE (buffer))
|
|
||||||
goto write_error;
|
/* else go to our error handler */
|
||||||
|
goto write_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* all is fine when we get here */
|
||||||
|
size -= written;
|
||||||
|
data += written;
|
||||||
|
fdsink->bytes_written += written;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (fdsink, "wrote %d bytes, %d left", written, size);
|
||||||
|
|
||||||
|
/* short write, select and try to write the remainder */
|
||||||
|
if (G_UNLIKELY (size > 0))
|
||||||
|
goto again;
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
#ifndef HAVE_WIN32
|
#ifndef HAVE_WIN32
|
||||||
|
@ -345,19 +373,22 @@ gst_fd_sink_check_fd (GstFdSink * fdsink, int fd)
|
||||||
goto not_seekable;
|
goto not_seekable;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
GST_DEBUG ("File descriptor \"%d\" is seekable", fd);
|
GST_DEBUG_OBJECT (fdsink, "File descriptor \"%d\" is seekable", fd);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
invalid:
|
invalid:
|
||||||
GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE,
|
{
|
||||||
(_("File descriptor \"%d\" is not valid."), fd),
|
GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE,
|
||||||
("%s", g_strerror (errno)));
|
(_("File descriptor \"%d\" is not valid."), fd),
|
||||||
return FALSE;
|
("%s", g_strerror (errno)));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
not_seekable:
|
not_seekable:
|
||||||
GST_DEBUG ("File descriptor \"%d\" is a pipe", fd);
|
{
|
||||||
return TRUE;
|
GST_DEBUG_OBJECT (fdsink, "File descriptor \"%d\" is a pipe", fd);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -417,19 +448,22 @@ gst_fd_sink_update_fd (GstFdSink * fdsink, int new_fd)
|
||||||
if (new_fd < 0)
|
if (new_fd < 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (!gst_fd_sink_check_fd (fdsink, new_fd))
|
||||||
|
goto invalid;
|
||||||
|
|
||||||
|
/* assign the fd */
|
||||||
GST_OBJECT_LOCK (fdsink);
|
GST_OBJECT_LOCK (fdsink);
|
||||||
|
|
||||||
if (!gst_fd_sink_check_fd (fdsink, new_fd)) {
|
|
||||||
GST_OBJECT_UNLOCK (fdsink);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
fdsink->fd = new_fd;
|
fdsink->fd = new_fd;
|
||||||
g_free (fdsink->uri);
|
g_free (fdsink->uri);
|
||||||
fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd);
|
fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd);
|
||||||
|
|
||||||
GST_OBJECT_UNLOCK (fdsink);
|
GST_OBJECT_UNLOCK (fdsink);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
invalid:
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in a new issue