+2004-07-30 Wim Taymans <wim@fluendo.com>
+
+ * gst/tcp/gstmultifdsink.c: (gst_multifdsink_class_init),
+ (gst_multifdsink_add), (gst_multifdsink_remove),
+ (gst_multifdsink_clear), (gst_multifdsink_get_stats),
+ (gst_multifdsink_client_remove),
+ (gst_multifdsink_handle_client_write),
+ (gst_multifdsink_queue_buffer), (gst_multifdsink_handle_clients):
+ * gst/tcp/gstmultifdsink.h:
+ Recover from a select with a bad file descriptor by removing
+ the client.
+
2004-07-30 Thomas Vander Stichele <thomas at apestaart dot org>
* configure.ac:
GstTCPClient *client;
GTimeVal now;
+ GST_DEBUG_OBJECT (sink, "adding client on fd %d", fd);
+
/* create client datastructure */
client = g_new0 (GstTCPClient, 1);
client->fd = fd;
+ client->bad = FALSE;
client->bufpos = -1;
client->bufoffset = 0;
client->sending = NULL;
{
GList *clients;
+ GST_DEBUG_OBJECT (sink, "removing client on fd %d", fd);
+
g_mutex_lock (sink->clientslock);
/* loop over the clients to find the one with the fd */
for (clients = sink->clients; clients; clients = g_list_next (clients)) {
void
gst_multifdsink_clear (GstMultiFdSink * sink)
{
+ GST_DEBUG_OBJECT (sink, "clearing all clients");
+
g_mutex_lock (sink->clientslock);
while (sink->clients) {
GstTCPClient *client;
/* < 0 is an error, 0 just means a timeout happened */
if (result < 0) {
- GST_ELEMENT_ERROR (sink, RESOURCE, READ, (NULL),
- ("select failed: %s", g_strerror (errno)));
- return;
- }
-
- GST_LOG_OBJECT (sink, "%d sockets had action", result);
- GST_LOG_OBJECT (sink, "done select on server/client fds for reads");
- gst_multifdsink_debug_fdset (sink, &testreadfds);
- GST_LOG_OBJECT (sink, "done select on client fds for writes");
- gst_multifdsink_debug_fdset (sink, &testwritefds);
-
- /* read all commands */
- if (FD_ISSET (READ_SOCKET (sink), &testreadfds)) {
- while (TRUE) {
- gchar command;
- int res;
-
- READ_COMMAND (sink, command, res);
- if (res < 0) {
- /* no more commands */
- break;
+ GST_WARNING_OBJECT (sink, "select failed: %s", g_strerror (errno));
+ if (errno == EBADF) {
+ /* ok, so one of the fds is invalid. We loop over them to find one
+ * that gives an error to the F_GETFL fcntl.
+ */
+ g_mutex_lock (sink->clientslock);
+ for (clients = sink->clients; clients; clients = g_list_next (clients)) {
+ GstTCPClient *client;
+ int fd;
+ long flags;
+ int res;
+
+ client = (GstTCPClient *) clients->data;
+ fd = client->fd;
+
+ res = fcntl (fd, F_GETFL, &flags);
+ if (res == -1) {
+ GST_WARNING_OBJECT (sink, "fnctl failed for %d, marking as bad: %s",
+ fd, g_strerror (errno));
+ if (errno == EBADF) {
+ client->bad = TRUE;
+ }
+ }
}
-
- switch (command) {
- case CONTROL_RESTART:
- /* need to restart the select call as the fd_set changed */
- try_again = TRUE;
- break;
- case CONTROL_STOP:
- /* stop this function */
- stop = TRUE;
- break;
- default:
- g_warning ("multifdsink: unknown control message received");
+ g_mutex_unlock (sink->clientslock);
+ } else if (errno == EINTR) {
+ try_again = TRUE;
+ } else {
+ GST_ELEMENT_ERROR (sink, RESOURCE, READ, (NULL),
+ ("select failed: %s", g_strerror (errno)));
+ return;
+ }
+ } else {
+ GST_LOG_OBJECT (sink, "%d sockets had action", result);
+ GST_LOG_OBJECT (sink, "done select on server/client fds for reads");
+ gst_multifdsink_debug_fdset (sink, &testreadfds);
+ GST_LOG_OBJECT (sink, "done select on client fds for writes");
+ gst_multifdsink_debug_fdset (sink, &testwritefds);
+
+ /* read all commands */
+ if (FD_ISSET (READ_SOCKET (sink), &testreadfds)) {
+ while (TRUE) {
+ gchar command;
+ int res;
+
+ READ_COMMAND (sink, command, res);
+ if (res < 0) {
+ /* no more commands */
break;
+ }
+
+ switch (command) {
+ case CONTROL_RESTART:
+ /* need to restart the select call as the fd_set changed */
+ try_again = TRUE;
+ break;
+ case CONTROL_STOP:
+ /* stop this function */
+ stop = TRUE;
+ break;
+ default:
+ g_warning ("multifdsink: unknown control message received");
+ break;
+ }
}
}
}
int fd;
client = (GstTCPClient *) clients->data;
+ if (client->bad) {
+ error = g_list_prepend (error, client);
+ continue;
+ }
+
fd = client->fd;
if (FD_ISSET (fd, &testreadfds)) {