This is an automated email from the ASF dual-hosted git repository.

robertlazarski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/axis-axis2-c-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 3ee110729 fix http transport unit tests
3ee110729 is described below

commit 3ee110729a49c6e288c2fd27e327584099b1b1b8
Author: Robert Lazarski <[email protected]>
AuthorDate: Sat Jan 10 06:47:53 2026 -1000

    fix http transport unit tests
---
 docs/HTTP2_JSON_REQUEST_CODE_PATH.md               | 207 +++++++++++++++++++++
 include/axis2_msg_recv.h                           |  15 ++
 src/core/engine/engine.c                           |  14 +-
 src/core/receivers/msg_recv.c                      |  46 +++--
 src/core/receivers/raw_xml_in_out_msg_recv.c       |  21 +++
 .../transport/http/util/http_transport_utils.c     |  39 +++-
 6 files changed, 320 insertions(+), 22 deletions(-)

diff --git a/docs/HTTP2_JSON_REQUEST_CODE_PATH.md 
b/docs/HTTP2_JSON_REQUEST_CODE_PATH.md
index 8bf4b664d..2d2e935f2 100644
--- a/docs/HTTP2_JSON_REQUEST_CODE_PATH.md
+++ b/docs/HTTP2_JSON_REQUEST_CODE_PATH.md
@@ -865,3 +865,210 @@ With all fixes deployed, HTTP/2 JSON services achieve:
 **Client Experience**: Clean, single JSON responses for all HTTP/2 requests 
with zero issues.
 
 This represents the **complete resolution** of all known HTTP/2 JSON 
processing issues in Apache Axis2/C. The system now delivers enterprise-grade 
HTTP/2 JSON web service functionality with reliability equivalent to 
traditional HTTP/1.1 SOAP services.
+
+---
+
+## January 2026 Update: Conditional Compilation Regression Fix
+
+### Issue: HTTP/1.1 SOAP Tests Crashing After HTTP/2 JSON Changes
+
+**Date:** January 2026
+**Symptom:** SEGV crash in `raw_xml_in_out_msg_recv.c:209` during HTTP/1.1 
SOAP tests
+**Root Cause:** Two separate issues introduced when adding HTTP/2 JSON support
+
+### Problem 1: Missing Conditional Compilation Guards
+
+The HTTP/2 JSON changes in `msg_recv.c` removed SOAP skeleton initialization 
code **unconditionally** instead of using `#ifdef WITH_NGHTTP2` guards.
+
+**Original Code (Broken):**
+```c
+/* HTTP/2 Pure JSON Architecture - removed skeleton init */
+if(impl_class)
+{
+    /* Generic JSON service initialization - no SOAP skeleton needed */
+}
+```
+
+**Fixed Code:**
+```c
+if(impl_class)
+{
+#ifndef WITH_NGHTTP2
+    /* HTTP/1.1 SOAP mode - Full skeleton initialization */
+    axis2_svc_skeleton_t *skel = (axis2_svc_skeleton_t *)impl_class;
+    if (skel->ops && skel->ops->init)
+    {
+        skel->ops->init(skel, env);
+    }
+#else
+    /* HTTP/2 JSON mode - Generic initialization */
+#endif
+}
+```
+
+**Files Modified:**
+- `src/core/receivers/msg_recv.c` - Added `#ifndef WITH_NGHTTP2` guards in two 
functions
+
+### Problem 2: Missing Function Declaration (ROOT CAUSE of Crash)
+
+The function `axis2_msg_recv_make_new_svc_obj` was **not declared** in any 
header file. Without a declaration, C assumes it returns `int` (32-bit), 
causing **pointer truncation** on 64-bit systems.
+
+**Symptom:** Compiler warning:
+```
+warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
+   99 |     svc_obj = (axis2_svc_skeleton_t 
*)axis2_msg_recv_make_new_svc_obj(...);
+```
+
+**Impact:** 64-bit pointers truncated to 32-bit, causing invalid memory access
+
+**Fix Added to `include/axis2_msg_recv.h`:**
+```c
+/**
+ * Create or retrieve the service implementation object.
+ * HTTP/1.1 SOAP mode: Returns axis2_svc_skeleton_t* with full skeleton 
initialization
+ * HTTP/2 JSON mode: Returns generic void* for JSON service implementation
+ */
+AXIS2_EXPORT void *AXIS2_CALL
+axis2_msg_recv_make_new_svc_obj(
+    axis2_msg_recv_t * msg_recv,
+    const axutil_env_t * env,
+    struct axis2_msg_ctx * msg_ctx);
+```
+
+### Problem 3: Safety Checks Added
+
+**File:** `src/core/receivers/raw_xml_in_out_msg_recv.c`
+
+Added defensive null checks before invoking service skeleton:
+
+```c
+if(status == AXIS2_SUCCESS)
+{
+    skel_invoked = AXIS2_TRUE;
+#ifndef WITH_NGHTTP2
+    /* HTTP/1.1 SOAP mode - Verify skeleton before invoke */
+    if(!svc_obj->ops)
+    {
+        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+            "Service skeleton ops is NULL - skeleton not properly 
initialized");
+        status = AXIS2_FAILURE;
+    }
+    else if(!svc_obj->ops->invoke)
+    {
+        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+            "Service skeleton invoke function is NULL");
+        status = AXIS2_FAILURE;
+    }
+    else
+    {
+        result_node = svc_obj->ops->invoke(svc_obj, env, om_node, new_msg_ctx);
+    }
+#else
+    /* HTTP/2 JSON mode - Macro returns NULL safely */
+    result_node = AXIS2_SVC_SKELETON_INVOKE(svc_obj, env, om_node, 
new_msg_ctx);
+#endif
+}
+```
+
+### Conditional Compilation Summary
+
+| File | Guard | HTTP/1.1 SOAP Behavior | HTTP/2 JSON Behavior |
+|------|-------|------------------------|----------------------|
+| `axis2_svc_skeleton.h` | `#ifndef WITH_NGHTTP2` | Full struct + macros | 
typedef void + NULL macros |
+| `msg_recv.c` | `#ifndef WITH_NGHTTP2` | Skeleton init via ops->init() | No 
initialization |
+| `raw_xml_in_out_msg_recv.c` | `#ifndef WITH_NGHTTP2` | Direct ops->invoke() 
with safety checks | Macro returns NULL |
+
+### Build Mode Detection
+
+```bash
+# Check if HTTP/2 mode is enabled
+grep "WITH_NGHTTP2" config.h
+
+# If no match: HTTP/1.1 SOAP mode (full skeleton support)
+# If defined: HTTP/2 JSON mode (minimal skeleton compatibility)
+```
+
+### Testing After Fix
+
+```bash
+# HTTP/1.1 SOAP tests should pass
+make -C test/core/transport/http check
+
+# Expected result:
+# [==========] 8 tests from 1 test suite ran.
+# [  PASSED  ] 8 tests.
+```
+
+### Key Lessons Learned
+
+1. **Always use conditional compilation** when modifying shared code for 
HTTP/2 JSON support
+2. **Declare all public functions** in headers to prevent pointer truncation 
on 64-bit
+3. **Add defensive null checks** before dereferencing function pointers
+4. **Build chain matters**: Changes to receivers require engine rebuild
+
+---
+
+## Memory Leak Fix: Service Provider Singleton Pattern
+
+### Problem Description
+
+AddressSanitizer detected a 72-byte memory leak originating from 
`axis2_engine_service_provider_create`:
+
+```
+Direct leak of 72 byte(s) in 1 object(s) allocated from:
+    #1 axis2_engine_service_provider_create at 
axis2_engine_service_provider.c:210
+    #2 axis2_engine_create at engine.c:71
+    #3 axis2_http_transport_utils_process_http_post_request at 
http_transport_utils.c:899
+```
+
+### Root Cause
+
+The HTTP service provider was designed as a global singleton, but 
`axis2_engine_create` was creating a new provider instance on EVERY engine 
creation, overwriting the global and orphaning previous allocations:
+
+```c
+// ORIGINAL (LEAKY) CODE in engine.c:
+axis2_http_service_provider_t* service_provider = 
axis2_engine_service_provider_create(env);
+if (service_provider) {
+    axis2_http_service_provider_set_impl(env, service_provider);  // 
Overwrites existing!
+}
+```
+
+In a multi-request server:
+1. Request 1: Engine creates provider A, sets global → A
+2. Request 2: Engine creates provider B, sets global → B (provider A orphaned 
- LEAK!)
+3. Request 3: Engine creates provider C, sets global → C (provider B orphaned 
- LEAK!)
+
+### Solution
+
+Modified `axis2_engine_create` to check for existing provider before creating:
+
+```c
+// FIXED CODE in engine.c:
+axis2_http_service_provider_t* existing_provider = 
axis2_http_service_provider_get_impl(env);
+if (!existing_provider) {
+    axis2_http_service_provider_t* service_provider = 
axis2_engine_service_provider_create(env);
+    if (service_provider) {
+        axis2_http_service_provider_set_impl(env, service_provider);
+    }
+}
+```
+
+### Files Modified
+
+| File | Change |
+|------|--------|
+| `src/core/engine/engine.c` | Check for existing provider before creating new 
one |
+
+### Verification
+
+```bash
+# Run tests with AddressSanitizer
+make -C test/core/transport/http check
+
+# Expected: PASS with no memory leak reports
+```
+
+---
+
+**Document Updated:** January 2026
+**Status:** HTTP/1.1 SOAP + HTTP/2 JSON dual-mode support fully functional (no 
memory leaks)
diff --git a/include/axis2_msg_recv.h b/include/axis2_msg_recv.h
index 92d28f6a0..e41682661 100644
--- a/include/axis2_msg_recv.h
+++ b/include/axis2_msg_recv.h
@@ -165,6 +165,21 @@ extern "C"
         axis2_msg_recv_t * msg_recv,
         const axutil_env_t * env);
 
+    /**
+     * Create or retrieve the service implementation object.
+     * HTTP/1.1 SOAP mode: Returns axis2_svc_skeleton_t* with full skeleton 
initialization
+     * HTTP/2 JSON mode: Returns generic void* for JSON service implementation
+     * @param msg_recv pointer to message receiver
+     * @param env pointer to environment struct
+     * @param msg_ctx pointer to message context
+     * @return pointer to service implementation object, or NULL on failure
+     */
+    AXIS2_EXPORT void *AXIS2_CALL
+    axis2_msg_recv_make_new_svc_obj(
+        axis2_msg_recv_t * msg_recv,
+        const axutil_env_t * env,
+        struct axis2_msg_ctx * msg_ctx);
+
     /**
      * Delete the service skeleton object created by make_new_svc_obj
      * @param msg_recv pointer to message receiver
diff --git a/src/core/engine/engine.c b/src/core/engine/engine.c
index 5bf912a34..34bf310b8 100644
--- a/src/core/engine/engine.c
+++ b/src/core/engine/engine.c
@@ -66,11 +66,15 @@ axis2_engine_create(
         engine->conf_ctx = conf_ctx;
     }
 
-    /* Register HTTP service provider implementation to eliminate circular 
dependency */
+    /* Register HTTP service provider implementation to eliminate circular 
dependency.
+     * Only create if not already set (true singleton pattern). */
     {
-        axis2_http_service_provider_t* service_provider = 
axis2_engine_service_provider_create(env);
-        if (service_provider) {
-            axis2_http_service_provider_set_impl(env, service_provider);
+        axis2_http_service_provider_t* existing_provider = 
axis2_http_service_provider_get_impl(env);
+        if (!existing_provider) {
+            axis2_http_service_provider_t* service_provider = 
axis2_engine_service_provider_create(env);
+            if (service_provider) {
+                axis2_http_service_provider_set_impl(env, service_provider);
+            }
         }
     }
 
@@ -82,7 +86,7 @@ axis2_engine_free(
     axis2_engine_t * engine,
     const axutil_env_t * env)
 {
-    /* REVOLUTIONARY: Clean up HTTP service provider */
+    /* Clean up HTTP service provider singleton */
     axis2_http_service_provider_t* service_provider = 
axis2_http_service_provider_get_impl(env);
     if (service_provider) {
         service_provider->free(service_provider, env);
diff --git a/src/core/receivers/msg_recv.c b/src/core/receivers/msg_recv.c
index f6d9dba13..c64ab7eb2 100644
--- a/src/core/receivers/msg_recv.c
+++ b/src/core/receivers/msg_recv.c
@@ -25,6 +25,9 @@
 #include <axiom_soap_envelope.h>
 #include <axiom_soap_body.h>
 #include <axutil_thread.h>
+#ifndef WITH_NGHTTP2
+#include <axis2_svc_skeleton.h>
+#endif
 
 struct axis2_msg_recv
 {
@@ -137,16 +140,20 @@ axis2_msg_recv_load_and_init_svc_impl(
     impl_class = axutil_class_loader_create_dll(env, impl_info_param);
     AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "loading the services from 
msg_recv_load_and_init_svc");
 
-    /* HTTP/2 Pure JSON Architecture - Generic JSON service initialization
-     * Replaced SOAP skeleton initialization with generic approach
-     * as SOAP skeletons are incompatible with HTTP/2 JSON-only design
-     */
     if(impl_class)
     {
-        /* Generic JSON service initialization - no SOAP skeleton operations 
needed */
-        axis2_conf_t *conf = NULL;
-        conf = axis2_conf_ctx_get_conf(msg_recv->conf_ctx, env);
-        /* JSON services initialized generically without skeleton-specific 
operations */
+#ifndef WITH_NGHTTP2
+        /* HTTP/1.1 SOAP mode - Full skeleton initialization */
+        axis2_svc_skeleton_t *skel = (axis2_svc_skeleton_t *)impl_class;
+        if (skel->ops && skel->ops->init)
+        {
+            skel->ops->init(skel, env);
+        }
+#else
+        /* HTTP/2 JSON mode - Generic JSON service initialization
+         * SOAP skeletons are incompatible with HTTP/2 JSON-only design
+         */
+#endif
     }
 
     axis2_svc_set_impl_class(svc, env, impl_class);
@@ -199,9 +206,10 @@ axis2_msg_recv_free(
     return;
 }
 
-/* HTTP/2 Pure JSON Architecture - Generic JSON service object creation
- * Replaced SOAP skeleton pattern with generic JSON service implementation
- * as SOAP skeletons are incompatible with HTTP/2 JSON-only design
+/*
+ * Create or retrieve service implementation object.
+ * HTTP/1.1 SOAP mode: Returns axis2_svc_skeleton_t* with full skeleton 
initialization
+ * HTTP/2 JSON mode: Returns generic void* for JSON service implementation
  */
 AXIS2_EXPORT void *AXIS2_CALL
 axis2_msg_recv_make_new_svc_obj(
@@ -257,12 +265,20 @@ axis2_msg_recv_make_new_svc_obj(
 
         impl_class = axutil_class_loader_create_dll(env, impl_info_param);
 
-        /* HTTP/2 Pure JSON Architecture - Generic initialization for JSON 
services
-         * Replaced SOAP skeleton init with generic approach
-         */
         if(impl_class)
         {
-            /* Generic JSON service initialization - no SOAP skeleton needed */
+#ifndef WITH_NGHTTP2
+            /* HTTP/1.1 SOAP mode - Initialize service skeleton */
+            axis2_svc_skeleton_t *skel = (axis2_svc_skeleton_t *)impl_class;
+            if (skel->ops && skel->ops->init)
+            {
+                skel->ops->init(skel, env);
+            }
+#else
+            /* HTTP/2 JSON mode - Generic JSON service initialization
+             * SOAP skeletons are incompatible with HTTP/2 JSON-only design
+             */
+#endif
         }
 
         axis2_svc_set_impl_class(svc, env, impl_class);
diff --git a/src/core/receivers/raw_xml_in_out_msg_recv.c 
b/src/core/receivers/raw_xml_in_out_msg_recv.c
index 6acbca1f0..63a8b8cba 100644
--- a/src/core/receivers/raw_xml_in_out_msg_recv.c
+++ b/src/core/receivers/raw_xml_in_out_msg_recv.c
@@ -206,7 +206,28 @@ axis2_raw_xml_in_out_msg_recv_invoke_business_logic_sync(
         if(status == AXIS2_SUCCESS)
         {
             skel_invoked = AXIS2_TRUE;
+#ifndef WITH_NGHTTP2
+            /* HTTP/1.1 SOAP mode - Verify skeleton is properly initialized 
before invoke */
+            if(!svc_obj->ops)
+            {
+                AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+                    "Service skeleton ops is NULL - skeleton not properly 
initialized");
+                status = AXIS2_FAILURE;
+            }
+            else if(!svc_obj->ops->invoke)
+            {
+                AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+                    "Service skeleton invoke function is NULL");
+                status = AXIS2_FAILURE;
+            }
+            else
+            {
+                result_node = svc_obj->ops->invoke(svc_obj, env, om_node, 
new_msg_ctx);
+            }
+#else
+            /* HTTP/2 JSON mode - Use macro (returns NULL for JSON services) */
             result_node = AXIS2_SVC_SKELETON_INVOKE(svc_obj, env, om_node, 
new_msg_ctx);
+#endif
         }
 
         if(result_node)
diff --git a/src/core/transport/http/util/http_transport_utils.c 
b/src/core/transport/http/util/http_transport_utils.c
index 977de8331..db2bf689f 100644
--- a/src/core/transport/http/util/http_transport_utils.c
+++ b/src/core/transport/http/util/http_transport_utils.c
@@ -899,12 +899,24 @@ axis2_http_transport_utils_process_http_post_request(
     engine = axis2_engine_create(env, conf_ctx);
 
     if(!soap_envelope)
+    {
+        if(engine)
+        {
+            axis2_engine_free(engine, env);
+        }
         return AXIS2_FAILURE;
+    }
 
     soap_body = axiom_soap_envelope_get_body(soap_envelope, env);
 
     if(!soap_body)
+    {
+        if(engine)
+        {
+            axis2_engine_free(engine, env);
+        }
         return AXIS2_FAILURE;
+    }
 
     if(!is_svc_callback)
     {
@@ -1392,14 +1404,26 @@ axis2_http_transport_utils_process_http_put_request(
     engine = axis2_engine_create(env, conf_ctx);
 
     if(!soap_envelope)
+    {
+        if(engine)
+        {
+            axis2_engine_free(engine, env);
+        }
         return AXIS2_FAILURE;
+    }
 
     soap_body = axiom_soap_envelope_get_body(soap_envelope, env);
 
     if(!soap_body)
+    {
+        if(engine)
+        {
+            axis2_engine_free(engine, env);
+        }
         return AXIS2_FAILURE;
+    }
 
-    is_client_property = axis2_msg_ctx_get_property(msg_ctx, env, 
+    is_client_property = axis2_msg_ctx_get_property(msg_ctx, env,
             AXIS2_TRANPORT_IS_APPLICATION_CLIENT_SIDE);
     if(is_client_property)
     {
@@ -1531,6 +1555,10 @@ axis2_http_transport_utils_process_http_head_request(
     axis2_msg_ctx_set_soap_envelope(msg_ctx, env, soap_envelope);
     engine = axis2_engine_create(env, conf_ctx);
     axis2_engine_receive(engine, env, msg_ctx);
+    if(engine)
+    {
+        axis2_engine_free(engine, env);
+    }
     return AXIS2_TRUE;
 }
 
@@ -1601,6 +1629,10 @@ axis2_http_transport_utils_process_http_get_request(
 
     engine = axis2_engine_create(env, conf_ctx);
     axis2_engine_receive(engine, env, msg_ctx);
+    if(engine)
+    {
+        axis2_engine_free(engine, env);
+    }
     return AXIS2_TRUE;
 }
 
@@ -1670,9 +1702,12 @@ axis2_http_transport_utils_process_http_delete_request(
     }
     axis2_msg_ctx_set_soap_envelope(msg_ctx, env, soap_envelope);
 
-
     engine = axis2_engine_create(env, conf_ctx);
     axis2_engine_receive(engine, env, msg_ctx);
+    if(engine)
+    {
+        axis2_engine_free(engine, env);
+    }
     return AXIS2_TRUE;
 }
 

Reply via email to