# HG changeset patch # User Igor Sysoev # Date 1184101477 0 # Node ID be2b895d31e07dc3bc442cb217efde66556769a1 # Parent a3f8d6d17b940ab6867964ff9c2384273aec4c97 fix segfault when session was freed twice diff --git a/src/event/ngx_event_connect.h b/src/event/ngx_event_connect.h --- a/src/event/ngx_event_connect.h +++ b/src/event/ngx_event_connect.h @@ -13,50 +13,56 @@ #include -#define NGX_PEER_KEEPALIVE 1 -#define NGX_PEER_NEXT 2 -#define NGX_PEER_FAILED 4 +#define NGX_PEER_KEEPALIVE 1 +#define NGX_PEER_NEXT 2 +#define NGX_PEER_FAILED 4 typedef struct ngx_peer_connection_s ngx_peer_connection_t; typedef ngx_int_t (*ngx_event_get_peer_pt)(ngx_peer_connection_t *pc, void *data); -#if (NGX_SSL) -typedef void (*ngx_event_save_peer_pt)(ngx_peer_connection_t *pc, void *data); -#endif typedef void (*ngx_event_free_peer_pt)(ngx_peer_connection_t *pc, void *data, ngx_uint_t state); +#if (NGX_SSL) + +typedef ngx_int_t (*ngx_event_set_peer_session_pt)(ngx_peer_connection_t *pc, + void *data); +typedef void (*ngx_event_save_peer_session_pt)(ngx_peer_connection_t *pc, + void *data); +#endif struct ngx_peer_connection_s { - ngx_connection_t *connection; + ngx_connection_t *connection; - struct sockaddr *sockaddr; - socklen_t socklen; - ngx_str_t *name; + struct sockaddr *sockaddr; + socklen_t socklen; + ngx_str_t *name; - ngx_uint_t tries; + ngx_uint_t tries; - ngx_event_get_peer_pt get; - ngx_event_free_peer_pt free; - void *data; + ngx_event_get_peer_pt get; + ngx_event_free_peer_pt free; + void *data; #if (NGX_SSL) - ngx_ssl_session_t *ssl_session; - ngx_event_save_peer_pt save_session; + ngx_event_set_peer_session_pt set_session; + ngx_event_save_peer_session_pt save_session; #endif #if (NGX_THREADS) - ngx_atomic_t *lock; + ngx_atomic_t *lock; #endif - int rcvbuf; + int rcvbuf; + + ngx_log_t *log; - ngx_log_t *log; + unsigned cached:1; - unsigned cached:1; - unsigned log_error:2; /* ngx_connection_log_error_e */ + /* ngx_connection_log_error_e */ + unsigned log_error:2; }; diff --git a/src/http/modules/ngx_http_upstream_ip_hash_module.c b/src/http/modules/ngx_http_upstream_ip_hash_module.c --- a/src/http/modules/ngx_http_upstream_ip_hash_module.c +++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c @@ -198,9 +198,6 @@ ngx_http_upstream_get_ip_hash_peer(ngx_p pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; pc->name = &peer->name; -#if (NGX_SSL) - pc->ssl_session = peer->ssl_session; -#endif /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */ diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -657,7 +657,7 @@ ngx_http_upstream_ssl_init_connection(ng c->sendfile = 0; u->output.sendfile = 0; - if (ngx_ssl_set_session(c, u->peer.ssl_session) != NGX_OK) { + if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); return; diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -152,7 +152,10 @@ ngx_http_upstream_init_round_robin_peer( r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer; r->upstream->peer.tries = rrp->peers->number; #if (NGX_HTTP_SSL) - r->upstream->peer.save_session = ngx_http_upstream_save_round_robin_peer; + r->upstream->peer.set_session = + ngx_http_upstream_set_round_robin_peer_session; + r->upstream->peer.save_session = + ngx_http_upstream_save_round_robin_peer_session; #endif return NGX_OK; @@ -328,9 +331,6 @@ ngx_http_upstream_get_round_robin_peer(n pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; pc->name = &peer->name; -#if (NGX_SSL) - pc->ssl_session = peer->ssl_session; -#endif /* ngx_unlock_mutex(rrp->peers->mutex); */ @@ -408,29 +408,72 @@ ngx_http_upstream_free_round_robin_peer( #if (NGX_HTTP_SSL) -void -ngx_http_upstream_save_round_robin_peer(ngx_peer_connection_t *pc, void *data) +ngx_int_t +ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc, + void *data) { ngx_http_upstream_rr_peer_data_t *rrp = data; + ngx_int_t rc; ngx_ssl_session_t *ssl_session; ngx_http_upstream_rr_peer_t *peer; + peer = &rrp->peers->peer[rrp->current]; + + /* TODO: threads only mutex */ + /* ngx_lock_mutex(rrp->peers->mutex); */ + + ssl_session = peer->ssl_session; + + rc = ngx_ssl_set_session(pc->connection, ssl_session); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "set session: %p:%d", + ssl_session, ssl_session ? ssl_session->references : 0); + + /* ngx_unlock_mutex(rrp->peers->mutex); */ + + return rc; +} + + +void +ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc, + void *data) +{ + ngx_http_upstream_rr_peer_data_t *rrp = data; + + ngx_ssl_session_t *old_ssl_session, *ssl_session; + ngx_http_upstream_rr_peer_t *peer; + ssl_session = ngx_ssl_get_session(pc->connection); if (ssl_session == NULL) { return; } + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "save session: %p:%d", ssl_session, ssl_session->references); + peer = &rrp->peers->peer[rrp->current]; + /* TODO: threads only mutex */ /* ngx_lock_mutex(rrp->peers->mutex); */ + + old_ssl_session = peer->ssl_session; peer->ssl_session = ssl_session; + /* ngx_unlock_mutex(rrp->peers->mutex); */ - if (pc->ssl_session) { + if (old_ssl_session) { + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "old session: %p:%d", + old_ssl_session, old_ssl_session->references); + /* TODO: may block */ - ngx_ssl_free_session(pc->ssl_session); + + ngx_ssl_free_session(old_ssl_session); } } diff --git a/src/http/ngx_http_upstream_round_robin.h b/src/http/ngx_http_upstream_round_robin.h --- a/src/http/ngx_http_upstream_round_robin.h +++ b/src/http/ngx_http_upstream_round_robin.h @@ -30,7 +30,7 @@ typedef struct { ngx_uint_t down; /* unsigned down:1; */ #if (NGX_SSL) - ngx_ssl_session_t *ssl_session; + ngx_ssl_session_t *ssl_session; /* local to a process */ #endif } ngx_http_upstream_rr_peer_t; @@ -68,7 +68,10 @@ void ngx_http_upstream_free_round_robin_ void *data, ngx_uint_t state); #if (NGX_HTTP_SSL) -void ngx_http_upstream_save_round_robin_peer(ngx_peer_connection_t *pc, +ngx_int_t + ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc, + void *data); +void ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc, void *data); #endif