return ps? *ps : NULL;
}
-h2_io *h2_io_set_get_highest_prio(h2_io_set *set)
-{
- h2_io *highest = NULL;
- int i;
- for (i = 0; i < set->list->nelts; ++i) {
- h2_io *io = h2_io_IDX(set->list, i);
- if (!highest /*|| io-prio even higher */ ) {
- highest = io;
- }
- }
- return highest;
-}
-
static void h2_io_set_sort(h2_io_set *sp)
{
qsort(sp->list->elts, sp->list->nelts, sp->list->elt_size,
return APR_SUCCESS;
}
+static void remove_idx(h2_io_set *sp, int idx)
+{
+ int n;
+ --sp->list->nelts;
+ n = sp->list->nelts - idx;
+ if (n > 0) {
+ /* Close the hole in the array by moving the upper
+ * parts down one step.
+ */
+ h2_io **selts = (h2_io**)sp->list->elts;
+ memmove(selts + idx, selts + idx + 1, n * sizeof(h2_io*));
+ }
+}
+
h2_io *h2_io_set_remove(h2_io_set *sp, h2_io *io)
{
int i;
for (i = 0; i < sp->list->nelts; ++i) {
h2_io *e = h2_io_IDX(sp->list, i);
if (e == io) {
- int n;
- --sp->list->nelts;
- n = sp->list->nelts - i;
- if (n > 0) {
- /* Close the hole in the array by moving the upper
- * parts down one step.
- */
- h2_io **selts = (h2_io**)sp->list->elts;
- memmove(selts+i, selts+i+1, n * sizeof(h2_io*));
- }
+ remove_idx(sp, i);
return e;
}
}
return NULL;
}
+h2_io *h2_io_set_pop_highest_prio(h2_io_set *set)
+{
+ /* For now, this just removes the first element in the set.
+ * the name is misleading...
+ */
+ if (set->list->nelts > 0) {
+ h2_io *io = h2_io_IDX(set->list, 0);
+ remove_idx(set, 0);
+ return io;
+ }
+ return NULL;
+}
+
void h2_io_set_destroy_all(h2_io_set *sp)
{
int i;
apr_status_t h2_io_set_add(h2_io_set *set, struct h2_io *io);
h2_io *h2_io_set_get(h2_io_set *set, int stream_id);
-h2_io *h2_io_set_get_highest_prio(h2_io_set *set);
h2_io *h2_io_set_remove(h2_io_set *set, struct h2_io *io);
void h2_io_set_remove_all(h2_io_set *set);
void h2_io_set_iter(h2_io_set *set,
h2_io_set_iter_fn *iter, void *ctx);
+h2_io *h2_io_set_pop_highest_prio(h2_io_set *set);
+
#endif /* defined(__mod_h2__h2_io_set__) */
stream_destroy(m, stream, io);
}
else {
+ if (stream->rst_error) {
+ /* Forward error code to fail any further attempt to
+ * write to io */
+ h2_io_rst(io, stream->rst_error);
+ }
+ /* Remove io from ready set (if there), since we will never submit it */
+ h2_io_set_remove(m->ready_ios, io);
/* Add stream to closed set for cleanup when task is done */
h2_stream_set_add(m->closed, stream);
}
}
status = apr_thread_mutex_lock(m->lock);
if (APR_SUCCESS == status) {
- h2_io *io = h2_io_set_get_highest_prio(m->ready_ios);
+ 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_set_response(stream, io->response, io->bbout);
}
- h2_io_set_remove(m->ready_ios, io);
if (io->output_drained) {
apr_thread_cond_signal(io->output_drained);
}
}
else {
- ap_log_cerror(APLOG_MARK, APLOG_WARNING, APR_NOTFOUND, m->c,
- APLOGNO(02953) "h2_mplx(%ld): stream for response %d",
+ ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, APLOGNO(02953)
+ "h2_mplx(%ld): stream for response %d not found",
m->id, io->id);
+ /* 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.
+ */
}
}
apr_thread_mutex_unlock(m->lock);
"h2_stream(%ld-%d): closing with err=%d %s",
session->id, (int)stream->id, (int)error_code,
nghttp2_strerror(error_code));
+ h2_stream_rst(stream, error_code);
}
h2_stream_set_remove(session->streams, stream);