| 665 | } |
| 666 | |
| 667 | apr_status_t h2_c2_process(conn_rec *c2, apr_thread_t *thread, int worker_id) |
| 668 | { |
| 669 | h2_conn_ctx_t *conn_ctx = h2_conn_ctx_get(c2); |
| 670 | |
| 671 | ap_assert(conn_ctx); |
| 672 | ap_assert(conn_ctx->mplx); |
| 673 | |
| 674 | /* See the discussion at <https://github.com/icing/mod_h2/issues/195> |
| 675 | * |
| 676 | * Each conn_rec->id is supposed to be unique at a point in time. Since |
| 677 | * some modules (and maybe external code) uses this id as an identifier |
| 678 | * for the request_rec they handle, it needs to be unique for secondary |
| 679 | * connections also. |
| 680 | * |
| 681 | * The MPM module assigns the connection ids and mod_unique_id is using |
| 682 | * that one to generate identifier for requests. While the implementation |
| 683 | * works for HTTP/1.x, the parallel execution of several requests per |
| 684 | * connection will generate duplicate identifiers on load. |
| 685 | * |
| 686 | * The original implementation for secondary connection identifiers used |
| 687 | * to shift the master connection id up and assign the stream id to the |
| 688 | * lower bits. This was cramped on 32 bit systems, but on 64bit there was |
| 689 | * enough space. |
| 690 | * |
| 691 | * As issue 195 showed, mod_unique_id only uses the lower 32 bit of the |
| 692 | * connection id, even on 64bit systems. Therefore collisions in request ids. |
| 693 | * |
| 694 | * The way master connection ids are generated, there is some space "at the |
| 695 | * top" of the lower 32 bits on allmost all systems. If you have a setup |
| 696 | * with 64k threads per child and 255 child processes, you live on the edge. |
| 697 | * |
| 698 | * The new implementation shifts 8 bits and XORs in the worker |
| 699 | * id. This will experience collisions with > 256 h2 workers and heavy |
| 700 | * load still. There seems to be no way to solve this in all possible |
| 701 | * configurations by mod_h2 alone. |
| 702 | */ |
| 703 | c2->id = (c2->master->id << 8)^worker_id; |
| 704 | |
| 705 | if (!conn_ctx->pre_conn_done) { |
| 706 | ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c2, |
| 707 | "h2_c2(%s-%d), adding filters", |
| 708 | conn_ctx->id, conn_ctx->stream_id); |
| 709 | ap_add_input_filter("H2_C2_NET_IN", NULL, NULL, c2); |
| 710 | ap_add_output_filter("H2_C2_NET_CATCH_H1", NULL, NULL, c2); |
| 711 | ap_add_output_filter("H2_C2_NET_OUT", NULL, NULL, c2); |
| 712 | |
| 713 | c2_run_pre_connection(c2, ap_get_conn_socket(c2)); |
| 714 | conn_ctx->pre_conn_done = 1; |
| 715 | } |
| 716 | |
| 717 | ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c2, |
| 718 | "h2_c2(%s-%d): process connection", |
| 719 | conn_ctx->id, conn_ctx->stream_id); |
| 720 | |
| 721 | c2->current_thread = thread; |
| 722 | ap_run_process_connection(c2); |
| 723 | |
| 724 | ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c2, |
no test coverage detected