static gssize g_unix_output_stream_write (GOutputStream *stream, const void *buffer, gsize count, GCancellable *cancellable, GError **error) { GUnixOutputStream *unix_stream; gssize res; GPollFD poll_fds[2]; int poll_ret; unix_stream = G_UNIX_OUTPUT_STREAM (stream); if (g_cancellable_make_pollfd (cancellable, &poll_fds[1])) { poll_fds[0].fd = unix_stream->priv->fd; poll_fds[0].events = G_IO_OUT; do poll_ret = g_poll (poll_fds, 2, -1); while (poll_ret == -1 && errno == EINTR); g_cancellable_release_fd (cancellable); if (poll_ret == -1) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error writing to unix: %s"), g_strerror (errsv)); return -1; } } while (1) { if (g_cancellable_set_error_if_cancelled (cancellable, error)) return -1; res = write (unix_stream->priv->fd, buffer, count); if (res == -1) { int errsv = errno; if (errsv == EINTR) continue; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error writing to unix: %s"), g_strerror (errsv)); } break; } return res; }
static void gst_udpsrc_create_cancellable (GstUDPSrc * src) { GPollFD pollfd; src->cancellable = g_cancellable_new (); src->made_cancel_fd = g_cancellable_make_pollfd (src->cancellable, &pollfd); }
gboolean wing_overlap_wait_result (HANDLE hfile, OVERLAPPED *overlap, DWORD *transferred, GCancellable *cancellable) { GPollFD pollfd[2]; gboolean result = FALSE; gint num, npoll; #if GLIB_SIZEOF_VOID_P == 8 pollfd[0].fd = (gint64)overlap->hEvent; #else pollfd[0].fd = (gint)overlap->hEvent; #endif pollfd[0].events = G_IO_IN; num = 1; if (g_cancellable_make_pollfd (cancellable, &pollfd[1])) num++; loop: npoll = g_poll (pollfd, num, -1); if (npoll <= 0) /* error out, should never happen */ goto end; if (g_cancellable_is_cancelled (cancellable)) { /* CancelIO only cancels pending operations issued by the * current thread and since we're doing only sync operations, * this is safe.... */ /* CancelIoEx is only Vista+. Since we have only one overlap * operaton on this thread, we can just use: */ result = CancelIo (hfile); g_warn_if_fail (result); } result = GetOverlappedResult (overlap->hEvent, overlap, transferred, FALSE); if (result == FALSE && GetLastError () == ERROR_IO_INCOMPLETE && !g_cancellable_is_cancelled (cancellable)) goto loop; end: if (num > 1) g_cancellable_release_fd (cancellable); return result; }
/** * g_cancellable_get_fd: * @cancellable: a #GCancellable. * * Gets the file descriptor for a cancellable job. This can be used to * implement cancellable operations on Unix systems. The returned fd will * turn readable when @cancellable is cancelled. * * You are not supposed to read from the fd yourself, just check for * readable status. Reading to unset the readable status is done * with g_cancellable_reset(). * * After a successful return from this function, you should use * g_cancellable_release_fd() to free up resources allocated for * the returned file descriptor. * * See also g_cancellable_make_pollfd(). * * Returns: A valid file descriptor. %-1 if the file descriptor * is not supported, or on errors. **/ int g_cancellable_get_fd (GCancellable *cancellable) { GPollFD pollfd; if (cancellable == NULL) return -1; #ifdef G_OS_WIN32 pollfd.fd = -1; #else g_cancellable_make_pollfd (cancellable, &pollfd); #endif return pollfd.fd; }
/* * g_socket_condition_timed_wait: * * Provides g_socket_condition_timed_wait function for older * glib versions. It's a simplified version of the glib one * that should work with all glib version from glib-2.22. */ gboolean g_socket_condition_timed_wait(GSocket *socket,GIOCondition condition,gint64 timeout,GCancellable *cancellable,GError **error) { gint64 start_time; GPollFD poll_fd[2]; gint result; gint num; g_return_val_if_fail(G_IS_SOCKET(socket),FALSE); if(g_cancellable_set_error_if_cancelled(cancellable,error)) return FALSE; if(timeout != -1) timeout /= 1000; start_time = g_get_monotonic_time(); poll_fd[0].fd = g_socket_get_fd(socket); poll_fd[0].events = condition; num = 1; if(g_cancellable_make_pollfd(cancellable,&poll_fd[1])) num++; while(TRUE){ result = g_poll(poll_fd,num,timeout); if(result != -1 || errno != EINTR) break; if(timeout != -1){ timeout -= (g_get_monotonic_time () - start_time) * 1000; if(timeout < 0) timeout = 0; } } if(num > 1) g_cancellable_release_fd(cancellable); if(result == 0){ g_set_error_literal(error,G_IO_ERROR,G_IO_ERROR_TIMED_OUT, "Socket I/O timed out"); return FALSE; } return !g_cancellable_set_error_if_cancelled(cancellable,error); }
static gboolean byzanz_queue_input_stream_wait (ByzanzQueueInputStream *stream, GCancellable * cancellable, GError ** error) { GPollFD fd; guint n_fds; /* FIXME: Use a file monitor here */ /* Do the same thing that the UNIX tail program does: sleep a second */ n_fds = 0; if (cancellable) { g_cancellable_make_pollfd (cancellable, &fd); n_fds++; } g_poll (&fd, n_fds, 1000); return !g_cancellable_set_error_if_cancelled (cancellable, error); }
static gssize g_unix_input_stream_read (GInputStream *stream, void *buffer, gsize count, GCancellable *cancellable, GError **error) { GUnixInputStream *unix_stream; gssize res = -1; GPollFD poll_fds[2]; int nfds; int poll_ret; unix_stream = G_UNIX_INPUT_STREAM (stream); poll_fds[0].fd = unix_stream->priv->fd; poll_fds[0].events = G_IO_IN; if (unix_stream->priv->is_pipe_or_socket && g_cancellable_make_pollfd (cancellable, &poll_fds[1])) nfds = 2; else nfds = 1; while (1) { poll_fds[0].revents = poll_fds[1].revents = 0; do poll_ret = g_poll (poll_fds, nfds, -1); while (poll_ret == -1 && errno == EINTR); if (poll_ret == -1) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error reading from file descriptor: %s"), g_strerror (errsv)); break; } if (g_cancellable_set_error_if_cancelled (cancellable, error)) break; if (!poll_fds[0].revents) continue; res = read (unix_stream->priv->fd, buffer, count); if (res == -1) { int errsv = errno; if (errsv == EINTR || errsv == EAGAIN) continue; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error reading from file descriptor: %s"), g_strerror (errsv)); } break; } if (nfds == 2) g_cancellable_release_fd (cancellable); return res; }
static gboolean claim_op (GTlsConnectionBase *tls, GTlsConnectionBaseOp op, gboolean blocking, GCancellable *cancellable, GError **error) { try_again: if (g_cancellable_set_error_if_cancelled (cancellable, error)) return FALSE; g_mutex_lock (&tls->op_mutex); if (((op == G_TLS_CONNECTION_BASE_OP_HANDSHAKE || op == G_TLS_CONNECTION_BASE_OP_READ) && (tls->read_closing || tls->read_closed)) || ((op == G_TLS_CONNECTION_BASE_OP_HANDSHAKE || op == G_TLS_CONNECTION_BASE_OP_WRITE) && (tls->write_closing || tls->write_closed))) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, _("Connection is closed")); g_mutex_unlock (&tls->op_mutex); return FALSE; } if (tls->handshake_error && op != G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH && op != G_TLS_CONNECTION_BASE_OP_CLOSE_READ && op != G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE) { if (error) *error = g_error_copy (tls->handshake_error); g_mutex_unlock (&tls->op_mutex); return FALSE; } if (op != G_TLS_CONNECTION_BASE_OP_HANDSHAKE) { if (op != G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH && op != G_TLS_CONNECTION_BASE_OP_CLOSE_READ && op != G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE && tls->need_handshake && !tls->handshaking) { tls->handshaking = TRUE; if (!do_implicit_handshake (tls, blocking, cancellable, error)) { g_cancellable_reset (tls->waiting_for_op); g_mutex_unlock (&tls->op_mutex); return FALSE; } } if (tls->need_finish_handshake && tls->implicit_handshake) { GError *my_error = NULL; gboolean success; tls->need_finish_handshake = FALSE; g_mutex_unlock (&tls->op_mutex); success = finish_handshake (tls, tls->implicit_handshake, &my_error); g_clear_object (&tls->implicit_handshake); g_mutex_lock (&tls->op_mutex); if (op != G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH && op != G_TLS_CONNECTION_BASE_OP_CLOSE_READ && op != G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE && (!success || g_cancellable_set_error_if_cancelled (cancellable, &my_error))) { g_propagate_error (error, my_error); g_mutex_unlock (&tls->op_mutex); return FALSE; } g_clear_error (&my_error); } } if ((op != G_TLS_CONNECTION_BASE_OP_WRITE && tls->reading) || (op != G_TLS_CONNECTION_BASE_OP_READ && tls->writing) || (op != G_TLS_CONNECTION_BASE_OP_HANDSHAKE && tls->handshaking)) { GPollFD fds[2]; int nfds; g_cancellable_reset (tls->waiting_for_op); g_mutex_unlock (&tls->op_mutex); if (!blocking) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, _("Operation would block")); return FALSE; } g_cancellable_make_pollfd (tls->waiting_for_op, &fds[0]); if (g_cancellable_make_pollfd (cancellable, &fds[1])) nfds = 2; else nfds = 1; g_poll (fds, nfds, -1); if (nfds > 1) g_cancellable_release_fd (cancellable); goto try_again; } if (op == G_TLS_CONNECTION_BASE_OP_HANDSHAKE) tls->handshaking = TRUE; if (op == G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH || op == G_TLS_CONNECTION_BASE_OP_CLOSE_READ) tls->read_closing = TRUE; if (op == G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH || op == G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE) tls->write_closing = TRUE; if (op != G_TLS_CONNECTION_BASE_OP_WRITE) tls->reading = TRUE; if (op != G_TLS_CONNECTION_BASE_OP_READ) tls->writing = TRUE; g_mutex_unlock (&tls->op_mutex); return TRUE; }
static gboolean gst_net_client_internal_clock_start (GstNetClientInternalClock * self) { GSocketAddress *servaddr; GSocketAddress *myaddr; GSocketAddress *anyaddr; GInetAddress *inetaddr; GSocket *socket; GError *error = NULL; GSocketFamily family; GPollFD dummy_pollfd; GResolver *resolver = NULL; GError *err = NULL; g_return_val_if_fail (self->address != NULL, FALSE); g_return_val_if_fail (self->servaddr == NULL, FALSE); /* create target address */ inetaddr = g_inet_address_new_from_string (self->address); if (inetaddr == NULL) { GList *results; resolver = g_resolver_get_default (); results = g_resolver_lookup_by_name (resolver, self->address, NULL, &err); if (!results) goto failed_to_resolve; inetaddr = G_INET_ADDRESS (g_object_ref (results->data)); g_resolver_free_addresses (results); g_object_unref (resolver); } family = g_inet_address_get_family (inetaddr); servaddr = g_inet_socket_address_new (inetaddr, self->port); g_object_unref (inetaddr); g_assert (servaddr != NULL); GST_DEBUG_OBJECT (self, "will communicate with %s:%d", self->address, self->port); socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error); if (socket == NULL) goto no_socket; GST_DEBUG_OBJECT (self, "binding socket"); inetaddr = g_inet_address_new_any (family); anyaddr = g_inet_socket_address_new (inetaddr, 0); g_socket_bind (socket, anyaddr, TRUE, &error); g_object_unref (anyaddr); g_object_unref (inetaddr); if (error != NULL) goto bind_error; /* check address we're bound to, mostly for debugging purposes */ myaddr = g_socket_get_local_address (socket, &error); if (myaddr == NULL) goto getsockname_error; GST_DEBUG_OBJECT (self, "socket opened on UDP port %d", g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (myaddr))); g_object_unref (myaddr); self->cancel = g_cancellable_new (); self->made_cancel_fd = g_cancellable_make_pollfd (self->cancel, &dummy_pollfd); self->socket = socket; self->servaddr = G_SOCKET_ADDRESS (servaddr); self->thread = g_thread_try_new ("GstNetClientInternalClock", gst_net_client_internal_clock_thread, self, &error); if (error != NULL) goto no_thread; return TRUE; /* ERRORS */ no_socket: { GST_ERROR_OBJECT (self, "socket_new() failed: %s", error->message); g_error_free (error); return FALSE; } bind_error: { GST_ERROR_OBJECT (self, "bind failed: %s", error->message); g_error_free (error); g_object_unref (socket); return FALSE; } getsockname_error: { GST_ERROR_OBJECT (self, "get_local_address() failed: %s", error->message); g_error_free (error); g_object_unref (socket); return FALSE; } failed_to_resolve: { GST_ERROR_OBJECT (self, "resolving '%s' failed: %s", self->address, err->message); g_clear_error (&err); g_object_unref (resolver); return FALSE; } no_thread: { GST_ERROR_OBJECT (self, "could not create thread: %s", error->message); g_object_unref (self->servaddr); self->servaddr = NULL; g_object_unref (self->socket); self->socket = NULL; g_error_free (error); return FALSE; } }
static gboolean g_unix_output_stream_writev (GOutputStream *stream, const GOutputVector *vectors, gsize n_vectors, gsize *bytes_written, GCancellable *cancellable, GError **error) { GUnixOutputStream *unix_stream; gssize res = -1; GPollFD poll_fds[2]; int nfds = 0; int poll_ret; struct iovec *iov; if (bytes_written) *bytes_written = 0; /* Clamp to G_MAXINT as writev() takes an integer for the number of vectors. * We handle this like a short write in this case */ if (n_vectors > G_MAXINT) n_vectors = G_MAXINT; unix_stream = G_UNIX_OUTPUT_STREAM (stream); if (G_OUTPUT_VECTOR_IS_IOVEC) { /* ABI is compatible */ iov = (struct iovec *) vectors; } else { gsize i; /* ABI is incompatible */ iov = g_newa (struct iovec, n_vectors); for (i = 0; i < n_vectors; i++) { iov[i].iov_base = (void *)vectors[i].buffer; iov[i].iov_len = vectors[i].size; } } poll_fds[0].fd = unix_stream->priv->fd; poll_fds[0].events = G_IO_OUT; nfds++; if (unix_stream->priv->is_pipe_or_socket && g_cancellable_make_pollfd (cancellable, &poll_fds[1])) nfds++; while (1) { int errsv; poll_fds[0].revents = poll_fds[1].revents = 0; do { poll_ret = g_poll (poll_fds, nfds, -1); errsv = errno; } while (poll_ret == -1 && errsv == EINTR); if (poll_ret == -1) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error writing to file descriptor: %s"), g_strerror (errsv)); break; } if (g_cancellable_set_error_if_cancelled (cancellable, error)) break; if (!poll_fds[0].revents) continue; res = writev (unix_stream->priv->fd, iov, n_vectors); errsv = errno; if (res == -1) { if (errsv == EINTR || errsv == EAGAIN) continue; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error writing to file descriptor: %s"), g_strerror (errsv)); } if (bytes_written) *bytes_written = res; break; } if (nfds == 2) g_cancellable_release_fd (cancellable); return res != -1; }