]> git.kaiwu.me - nginx.git/commitdiff
fix segfault when session was freed twice
authorIgor Sysoev <igor@sysoev.ru>
Tue, 10 Jul 2007 21:04:37 +0000 (21:04 +0000)
committerIgor Sysoev <igor@sysoev.ru>
Tue, 10 Jul 2007 21:04:37 +0000 (21:04 +0000)
src/event/ngx_event_connect.h
src/http/modules/ngx_http_upstream_ip_hash_module.c
src/http/ngx_http_upstream.c
src/http/ngx_http_upstream_round_robin.c
src/http/ngx_http_upstream_round_robin.h

index f8a7de944b216b0290e83bb1cf9b519ae0dd7f50..6cad0427974ef4e9ca84c8d4f2c72887f521138a 100644 (file)
 #include <ngx_event.h>
 
 
-#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;
 };
 
 
index ba1cd53ff91d9ef0853fda2bbd542b74660506c9..3ef424921b15b1012d7ebc9beaffe5cfc9a17995 100644 (file)
@@ -198,9 +198,6 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
     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); */
 
index c1bae266c63103b75722bd6dd30e5f51be24d9c1..d01941a867165ad2ca32cc094922fb056acb0ad4 100644 (file)
@@ -657,7 +657,7 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
     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;
index b54e7a72d81d7ce05afa153d6fb0eb5e319fdbe6..af90d1d596e560cb087e770e5bc71be0d3b1166c 100644 (file)
@@ -152,7 +152,10 @@ ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,
     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(ngx_peer_connection_t *pc, void *data)
     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(ngx_peer_connection_t *pc, void *data,
 
 #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);
     }
 }
 
index 5d952217ba20d16addad01ba3457ab9ff75675ab..2e2bf132fc8301e78e2903e54fec98997d5433e7 100644 (file)
@@ -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_peer(ngx_peer_connection_t *pc,
     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