static void directtcp_connection_finalize(GObject *goself) { DirectTCPConnection *self = DIRECTTCP_CONNECTION(goself); /* close this socket if necessary, failing fatally if that doesn't work */ if (!self->closed) { char *errmsg; g_warning("connection freed without being closed first; any error will be fatal"); errmsg = directtcp_connection_close(self); if (errmsg) error("while closing directtcp connection: %s", errmsg); } G_OBJECT_CLASS(parent_class)->finalize(goself); }
/* common code for both directtcp_listen_thread and directtcp_connect_thread; * this is called after self->conn is filled in and carries out the data * transfer over that connection. NOTE: start_part_mutex is HELD when this * function begins */ static gpointer directtcp_common_thread( XferSourceRecovery *self) { XferElement *elt = XFER_ELEMENT(self); char *errmsg = NULL; int result; /* send XMSG_READY to indicate it's OK to call start_part now */ DBG(2, "directtcp_common_thread sending XMSG_READY"); xfer_queue_message(elt->xfer, xmsg_new(elt, XMSG_READY, 0)); /* now we sit around waiting for signals to write a part */ while (1) { guint64 actual_size; XMsg *msg; while (self->paused && !elt->cancelled) { DBG(9, "directtcp_common_thread waiting to be un-paused"); g_cond_wait(self->start_part_cond, self->start_part_mutex); } DBG(9, "directtcp_common_thread done waiting"); if (elt->cancelled) { g_mutex_unlock(self->start_part_mutex); goto close_conn_and_send_done; } /* if the device is NULL, we're done */ if (!self->device) break; /* read the part */ self->part_timer = g_timer_new(); while (1) { DBG(2, "directtcp_common_thread reading part from %s", self->device->device_name); result = device_read_to_connection(self->device, G_MAXUINT64, &actual_size, &elt->cancelled, self->start_part_mutex, self->abort_cond); if (result == 1 && !elt->cancelled) { xfer_cancel_with_error(elt, _("error reading from device: %s"), device_error_or_status(self->device)); g_mutex_unlock(self->start_part_mutex); goto close_conn_and_send_done; } else if (result == 2 || elt->cancelled) { g_mutex_unlock(self->start_part_mutex); goto close_conn_and_send_done; } /* break on EOF; otherwise do another read_to_connection */ if (self->device->is_eof) { break; } } DBG(2, "done reading part; sending XMSG_PART_DONE"); /* the device has signalled EOF (really end-of-part), so clean up instance * variables and report the EOP to the caller in the form of an xmsg */ msg = xmsg_new(XFER_ELEMENT(self), XMSG_PART_DONE, 0); msg->size = actual_size; msg->duration = g_timer_elapsed(self->part_timer, NULL); msg->partnum = 0; msg->fileno = self->device->file; msg->successful = TRUE; msg->eof = FALSE; self->paused = TRUE; g_object_unref(self->device); self->device = NULL; self->part_size = 0; self->block_size = 0; g_timer_destroy(self->part_timer); self->part_timer = NULL; xfer_queue_message(elt->xfer, msg); } g_mutex_unlock(self->start_part_mutex); close_conn_and_send_done: if (self->conn) { errmsg = directtcp_connection_close(self->conn); g_object_unref(self->conn); self->conn = NULL; if (errmsg) { xfer_cancel_with_error(elt, _("error closing DirectTCP connection: %s"), errmsg); wait_until_xfer_cancelled(elt->xfer); } } xfer_queue_message(elt->xfer, xmsg_new(elt, XMSG_DONE, 0)); return NULL; }