Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.4.0
    • Fix Version/s: 1.7.0
    • Component/s: transport/http
    • Labels:
      None
    • Environment:
      Fedora 9 (i386), openssl-0.9.8g-9.fc9

      Description

      I've written small client using Axis2C and I've noticed memory leaks
      when connecting to service with https.

      I've checked with the valgrind and got following results:
      valgrind --leak-check=full
      ==8057== 58,000 (292 direct, 57,708 indirect) bytes in 1 blocks are
      definitely lost in loss record 9 of 9
      ==8057== at 0x4006AEE: malloc (vg_replace_malloc.c:207)
      ==8057== by 0x7B4E4CD: (within /lib/libcrypto.so.0.9.8g)
      ==8057== by 0x7B4EB4E: CRYPTO_malloc (in /lib/libcrypto.so.0.9.8g)
      ==8057== by 0x34C529: SSL_new (in /lib/libssl.so.0.9.8g)
      ==8057== by 0x40EB9C2: axis2_ssl_utils_initialize_ssl (ssl_utils.c:133)
      ==8057== by 0x40EB7E6: axutil_stream_create_ssl (ssl_stream.c:104)
      ==8057== by 0x40EABB1: axis2_http_client_send (http_client.c:216)
      ==8057== by 0x40E8A9D: axis2_http_sender_send (http_sender.c:1064)
      ==8057== by 0x40E32B4: axis2_http_transport_sender_write_message
      (http_transport_sender.c:771)
      ==8057== by 0x40E3AC3: axis2_http_transport_sender_invoke
      (http_transport_sender.c:306)
      ==8057== by 0x407DF6A: axis2_engine_send (engine.c:176)
      ==8057== by 0x40A5BAB: axis2_op_client_two_way_send (op_client.c:1157)
      .......
      ==8057== LEAK SUMMARY:
      ==8057== definitely lost: 332 bytes in 4 blocks.
      ==8057== indirectly lost: 57,900 bytes in 596 blocks.
      ==8057== possibly lost: 0 bytes in 0 blocks.
      ==8057== still reachable: 28,292 bytes in 1,887 blocks.
      ==8057== suppressed: 0 bytes in 0 blocks.

      As I expected when I changed https to plain http the problem disapeared:
      ==9065== LEAK SUMMARY:
      ==9065== definitely lost: 40 bytes in 3 blocks.
      ==9065== indirectly lost: 192 bytes in 6 blocks.
      ==9065== possibly lost: 0 bytes in 0 blocks.
      ==9065== still reachable: 300 bytes in 3 blocks.
      ==9065== suppressed: 0 bytes in 0 blocks.

      I looked at the code and it seems axis2_ssl_utils_cleanup_ssl function isn't called in case of successful connection.

        Issue Links

          Activity

          Hide
          S.Uthaiyashankar added a comment -

          Issue AXIS2C-1419 is related.

          Show
          S.Uthaiyashankar added a comment - Issue AXIS2C-1419 is related.
          Hide
          Steve Leland added a comment - - edited

          Hi,

          I am running on Windows Server 2008 R2, using a build I made Saturday (svn 957643) which staticly links in Openssl 0.9.8o, and find it to have the same problems as the 1.6.0 release in not being able to properly terminate its ssl processing - which leads to the stack reported in this bug report.

          The problem starts in http_sender.c axis2_http_sender_process_response(), where the ssl stream is added to a property which uses axutil_stream_free_void_arg as the free_func. For ssl streams it should be axis2_ssl_stream_free().

          The next issue is that the socket is closed prematurely by Axis2c code in http_client.c axis2_http_client_free(). Openssl's SSL_shutdown() and SSL_Free() should be allowed to do that when their internal reference counts indicate it's time.

          The final issue issue is that the SSL structure is never freed in ssl_utils.c axis2_ssl_utils_cleanup_ssl with a call to SSL_free().

          Diffs:

          Index: src/core/transport/http/sender/http_client.c
          ===================================================================
          — src/core/transport/http/sender/http_client.c (revision 958144)
          +++ src/core/transport/http/sender/http_client.c (working copy)
          @@ -120,7 +120,15 @@
          }
          if(1 != http_client>sockfd)

          { +#ifdef AXIS2_SSL_ENABLED + if (http_client->data_stream->stream_type == AXIS2_STREAM_SOCKET) + axutil_network_handler_close_socket(env, http_client->sockfd); +// else // ssl streams are AXIS2_STREAM_BASIC +// will be handled in SSL_shutdown() +#else axutil_network_handler_close_socket(env, http_client->sockfd); +#endif + http_client->sockfd = -1; }

          Index: src/core/transport/http/sender/http_sender.c
          ===================================================================
          — src/core/transport/http/sender/http_sender.c (revision 958144)
          +++ src/core/transport/http/sender/http_sender.c (working copy)
          @@ -43,6 +43,13 @@
          #define CLIENT_NONCE_LENGTH 8
          #endif

          +// expose private function is sender\ssl\ssl_stream.
          +#ifdef AXIS2_SSL_ENABLED
          +void AXIS2_CALL axis2_ssl_stream_free(
          + axutil_stream_t * stream,
          + const axutil_env_t * env);
          +#endif
          +
          struct axis2_http_sender
          {
          axis2_char_t *http_version;
          @@ -1594,7 +1601,16 @@
          response, env));
          property = axutil_property_create(env);
          axutil_property_set_scope(property, env, AXIS2_SCOPE_REQUEST);

          • axutil_property_set_free_func(property, env, axutil_stream_free_void_arg);
            +// fix ssl memory leak
            +#ifdef AXIS2_SSL_ENABLED
            + if (in_stream->stream_type == AXIS2_STREAM_SOCKET)
            + axutil_property_set_free_func (property, env, axutil_stream_free_void_arg);
            + else // ssl streams are AXIS2_STREAM_BASIC
            + axutil_property_set_free_func (property, env, axis2_ssl_stream_free);
            +#else
            + axutil_property_set_free_func (property, env, axutil_stream_free_void_arg);
            +#endif
            +
            axutil_property_set_value(property, env, in_stream);
            axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_TRANSPORT_IN, property);
            AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_sender_process_response");

          Index: src/core/transport/http/sender/ssl/ssl_utils.c
          ===================================================================
          — src/core/transport/http/sender/ssl/ssl_utils.c (revision 958144)
          +++ src/core/transport/http/sender/ssl/ssl_utils.c (working copy)
          @@ -214,7 +214,10 @@

          if (ssl)
          {

          • SSL_shutdown(ssl);
            + if (SSL_shutdown(ssl) == 0)
            + { + SSL_free(ssl); + }

            }
            if (ctx)
            {

          Regards,
          Steve

          Show
          Steve Leland added a comment - - edited Hi, I am running on Windows Server 2008 R2, using a build I made Saturday (svn 957643) which staticly links in Openssl 0.9.8o, and find it to have the same problems as the 1.6.0 release in not being able to properly terminate its ssl processing - which leads to the stack reported in this bug report. The problem starts in http_sender.c axis2_http_sender_process_response(), where the ssl stream is added to a property which uses axutil_stream_free_void_arg as the free_func. For ssl streams it should be axis2_ssl_stream_free(). The next issue is that the socket is closed prematurely by Axis2c code in http_client.c axis2_http_client_free(). Openssl's SSL_shutdown() and SSL_Free() should be allowed to do that when their internal reference counts indicate it's time. The final issue issue is that the SSL structure is never freed in ssl_utils.c axis2_ssl_utils_cleanup_ssl with a call to SSL_free(). Diffs: Index: src/core/transport/http/sender/http_client.c =================================================================== — src/core/transport/http/sender/http_client.c (revision 958144) +++ src/core/transport/http/sender/http_client.c (working copy) @@ -120,7 +120,15 @@ } if( 1 != http_client >sockfd) { +#ifdef AXIS2_SSL_ENABLED + if (http_client->data_stream->stream_type == AXIS2_STREAM_SOCKET) + axutil_network_handler_close_socket(env, http_client->sockfd); +// else // ssl streams are AXIS2_STREAM_BASIC +// will be handled in SSL_shutdown() +#else axutil_network_handler_close_socket(env, http_client->sockfd); +#endif + http_client->sockfd = -1; } Index: src/core/transport/http/sender/http_sender.c =================================================================== — src/core/transport/http/sender/http_sender.c (revision 958144) +++ src/core/transport/http/sender/http_sender.c (working copy) @@ -43,6 +43,13 @@ #define CLIENT_NONCE_LENGTH 8 #endif +// expose private function is sender\ssl\ssl_stream. +#ifdef AXIS2_SSL_ENABLED +void AXIS2_CALL axis2_ssl_stream_free( + axutil_stream_t * stream, + const axutil_env_t * env); +#endif + struct axis2_http_sender { axis2_char_t *http_version; @@ -1594,7 +1601,16 @@ response, env)); property = axutil_property_create(env); axutil_property_set_scope(property, env, AXIS2_SCOPE_REQUEST); axutil_property_set_free_func(property, env, axutil_stream_free_void_arg); +// fix ssl memory leak +#ifdef AXIS2_SSL_ENABLED + if (in_stream->stream_type == AXIS2_STREAM_SOCKET) + axutil_property_set_free_func (property, env, axutil_stream_free_void_arg); + else // ssl streams are AXIS2_STREAM_BASIC + axutil_property_set_free_func (property, env, axis2_ssl_stream_free); +#else + axutil_property_set_free_func (property, env, axutil_stream_free_void_arg); +#endif + axutil_property_set_value(property, env, in_stream); axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_TRANSPORT_IN, property); AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_sender_process_response"); Index: src/core/transport/http/sender/ssl/ssl_utils.c =================================================================== — src/core/transport/http/sender/ssl/ssl_utils.c (revision 958144) +++ src/core/transport/http/sender/ssl/ssl_utils.c (working copy) @@ -214,7 +214,10 @@ if (ssl) { SSL_shutdown(ssl); + if (SSL_shutdown(ssl) == 0) + { + SSL_free(ssl); + } } if (ctx) { Regards, Steve
          Hide
          Nandika Jayawardana added a comment -

          Patch applied

          Show
          Nandika Jayawardana added a comment - Patch applied
          Hide
          Maxi Combina added a comment -

          Is it possible to backport this patch to 1.6.0?
          I am using ssl connections under 1.6.0 and valgrind reports ~700K of leak in each invocation.
          I also tried to patch myself, but I get seg faults when axis2_ssl_stream_free() is invoked.

          Show
          Maxi Combina added a comment - Is it possible to backport this patch to 1.6.0? I am using ssl connections under 1.6.0 and valgrind reports ~700K of leak in each invocation. I also tried to patch myself, but I get seg faults when axis2_ssl_stream_free() is invoked.

            People

            • Assignee:
              Nandika Jayawardana
              Reporter:
              Rafal Metkowski
            • Votes:
              1 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development