static void io_destroy(h2_mplx *m, h2_io *io, int events) { apr_pool_t *pool = io->pool; /* cleanup any buffered input */ h2_io_in_shutdown(io); if (events) { /* Process outstanding events before destruction */ io_process_events(m, io); } io->pool = NULL; /* The pool is cleared/destroyed which also closes all * allocated file handles. Give this count back to our * file handle pool. */ m->tx_handles_reserved += io->files_handles_owned; h2_io_set_remove(m->stream_ios, io); h2_io_set_remove(m->ready_ios, io); h2_io_destroy(io); if (pool) { apr_pool_clear(pool); if (m->spare_pool) { apr_pool_destroy(m->spare_pool); } m->spare_pool = pool; } check_tx_free(m); }
apr_status_t h2_mplx_in_close(h2_mplx *m, int stream_id) { apr_status_t status; AP_DEBUG_ASSERT(m); if (m->aborted) { return APR_ECONNABORTED; } status = apr_thread_mutex_lock(m->lock); if (APR_SUCCESS == status) { h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io && !io->orphaned) { status = h2_io_in_close(io); H2_MPLX_IO_IN(APLOG_TRACE2, m, io, "h2_mplx_in_close"); if (io->input_arrived) { apr_thread_cond_signal(io->input_arrived); } io_process_events(m, io); } else { status = APR_ECONNABORTED; } apr_thread_mutex_unlock(m->lock); } return status; }
static int update_window(void *ctx, h2_io *io) { update_ctx *uctx = (update_ctx*)ctx; if (io_process_events(uctx->m, io)) { ++uctx->streams_updated; } return 1; }
h2_stream *h2_mplx_next_submit(h2_mplx *m, h2_stream_set *streams) { apr_status_t status; h2_stream *stream = NULL; AP_DEBUG_ASSERT(m); if (m->aborted) { return NULL; } status = apr_thread_mutex_lock(m->lock); if (APR_SUCCESS == status) { h2_io *io = h2_io_set_pop_highest_prio(m->ready_ios); if (io) { stream = h2_stream_set_get(streams, io->id); if (stream) { if (io->rst_error) { h2_stream_rst(stream, io->rst_error); } else { AP_DEBUG_ASSERT(io->response); H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_next_submit_pre"); h2_stream_set_response(stream, io->response, io->bbout); H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_next_submit_post"); } } else { /* We have the io ready, but the stream has gone away, maybe * reset by the client. Should no longer happen since such * streams should clear io's from the ready queue. */ ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, m->c, APLOGNO(02953) "h2_mplx(%ld): stream for response %d closed, " "resetting io to close request processing", m->id, io->id); io->orphaned = 1; if (io->task_done) { io_destroy(m, io, 1); } else { /* hang around until the h2_task is done, but * shutdown input and send out any events (e.g. window * updates) asap. */ h2_io_in_shutdown(io); h2_io_rst(io, H2_ERR_STREAM_CLOSED); io_process_events(m, io); } } if (io->output_drained) { apr_thread_cond_signal(io->output_drained); } } apr_thread_mutex_unlock(m->lock); } return stream; }
h2_stream *h2_mplx_next_submit(h2_mplx *m, h2_stream_set *streams) { apr_status_t status; h2_stream *stream = NULL; int acquired; AP_DEBUG_ASSERT(m); if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) { h2_io *io = h2_io_set_pop_highest_prio(m->ready_ios); if (io && !m->aborted) { stream = h2_stream_set_get(streams, io->id); if (stream) { if (io->rst_error) { h2_stream_rst(stream, io->rst_error); } else { AP_DEBUG_ASSERT(io->response); H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_next_submit_pre"); h2_stream_set_response(stream, io->response, io->bbout); H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_next_submit_post"); } } else { /* We have the io ready, but the stream has gone away, maybe * reset by the client. Should no longer happen since such * streams should clear io's from the ready queue. */ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c, "h2_mplx(%ld): stream for response %d closed, " "resetting io to close request processing", m->id, io->id); h2_io_make_orphaned(io, H2_ERR_STREAM_CLOSED); if (!io->worker_started || io->worker_done) { io_destroy(m, io, 1); } else { /* hang around until the h2_task is done, but * shutdown input and send out any events (e.g. window * updates) asap. */ h2_io_in_shutdown(io); io_process_events(m, io); } } h2_io_signal(io, H2_IO_WRITE); } leave_mutex(m, acquired); } return stream; }
apr_status_t h2_mplx_in_close(h2_mplx *m, int stream_id) { apr_status_t status; int acquired; AP_DEBUG_ASSERT(m); if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) { h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io && !io->orphaned) { status = h2_io_in_close(io); H2_MPLX_IO_IN(APLOG_TRACE2, m, io, "h2_mplx_in_close"); h2_io_signal(io, H2_IO_READ); io_process_events(m, io); } else { status = APR_ECONNABORTED; } leave_mutex(m, acquired); } return status; }