Help with TLS Socket Creation on Thingy53 - ENOMEM (Error 23)

I'm working on a Thingy53 project with Zephyr RTOS that requires TLS connections, but I'm encountering persistent "Failed to create TLS socket: 23" errors (ENOMEM - out of memory). I've implemented several memory optimizations and error handling strategies but still face issues with TLS socket creation.

  1. Initial Problem Identification

    • Thingy53 device experiencing ENOMEM errors during TLS socket creation
    • Memory allocation test function using undefined k_malloc_free_get
  2. Configuration Optimization

    • Consolidated duplicate definitions in prj.conf
    • Increased heap memory (CONFIG_HEAP_MEM_POOL_SIZE=180000)
    • Increased mbedTLS heap (CONFIG_MBEDTLS_HEAP_SIZE=80000)
    • Restored GPIO and WiFi management configurations
  3. TLS Cipher Configuration Issues

    • Identified problematic CONFIG_MBEDTLS_SSL_CIPHERSUITES configuration
    • Attempted various syntax fixes (removing quotes, escaping quotes)
    • Ultimately removed the problematic configuration to allow builds to proceed
  4. First Socket Implementation Approach

    • Tried incremental approach: TCP socket → Connect → TLS upgrade
    • Failed with ENOBUFS (error 109) when setting TLS_SEC_TAG_LIST
  5. Second Socket Implementation Approach

    • Created TLS socket directly using IPPROTO_TLS_1_2
    • Set all TLS options before connecting
    • Eliminated socket reconfiguration to allow proper resource allocation
  6. Memory Management Improvements

    • Implemented socket tracking system to prevent resource leaks
    • Added retry mechanism with increasing delays
    • Added specific ENOMEM error handling with resource cleanup
    • Improved TLS configuration sequence (hostname before security tags)
  7. Current Status

    • Despite improvements, still encountering ENOMEM (error 23)
    • Memory allocation test succeeds but TLS socket creation fails
    • Implemented more aggressive resource management with k_yield() and socket tracking
static int create_tls_socket(const char *hostname, struct sockaddr_in *server_addr)
{
    int sock;
    int ret;
    int retry_count = 0;
    const int retry_delay_ms = 1000;
    
    /* Check memory status before attempting socket creation */
    check_memory_status("before TLS socket creation");
    
    /* We'll try a different approach if the previous one keeps failing with ENOMEM */
    while (retry_count < MAX_SOCKET_RETRIES) {
        /* First, ensure any previous socket resources are fully released */
        k_sleep(K_MSEC(retry_delay_ms));
        k_yield();  /* Allow other threads to run and potentially free resources */
        
        /* Create TLS socket */
        sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
        if (sock < 0) {
            if (errno == ENOMEM) {
                LOG_ERR("Failed to create TLS socket: Out of memory (ENOMEM)");
                /* Try to release memory by forcing a garbage collection */
                close_all_sockets();
                retry_count++;
                continue;
            } else {
                LOG_ERR("Failed to create TLS socket: %d", errno);
                retry_count++;
                continue;
            }
        }
        
        LOG_INF("TLS socket created successfully");
        track_socket(sock);
        
        /* Set TLS socket options */
        sec_tag_t sec_tag_list[] = {
            CA_CERT_TAG,
        };
        
        /* Set receive and send timeout to avoid blocking indefinitely */
        struct timeval timeout = {
            .tv_sec = 10,
            .tv_usec = 0,
        };
        
        ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
        if (ret < 0) {
            LOG_ERR("Failed to set socket receive timeout: %d", errno);
            close(sock);
            untrack_socket(sock);
            retry_count++;
            continue;
        }
        
        // [Additional socket option settings omitted for brevity]
        
        /* All options set successfully */
        LOG_INF("TLS socket configured successfully");
        return sock;
    }
    
    LOG_ERR("Failed to create TLS socket after %d attempts", MAX_SOCKET_RETRIES);
    return -ENOMEM;
}

I'm tracking sockets and cleaning them up:
void track_socket(int sock)
{
// Track socket for potential cleanup
}

void untrack_socket(int sock)
{
// Remove socket from tracking
}

void close_all_sockets(void)
{
// Close all tracked sockets to free resources
}

I've made the following memory optimizations in prj.conf:

Increase heap memory pool size

CONFIG_HEAP_MEM_POOL_SIZE=200000
CONFIG_HEAP_MEM_POOL_IGNORE_MIN=y

TLS Configuration

CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_BUILTIN=y
CONFIG_MBEDTLS_ENABLE_HEAP=y
CONFIG_MBEDTLS_HEAP_SIZE=85000
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=1536

Reduce TLS resource usage

CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=2
CONFIG_NET_SOCKETS_TLS_MAX_CREDENTIALS=2
CONFIG_NET_CONTEXT_MAX_CONN=4

Are there additional memory optimizations I should be making for TLS on constrained devices like the Thingy53?
Could there be any memory leaks or resource allocation issues that I'm missing in my implementation?
Are there specific mbedTLS configurations I should be adjusting to reduce memory usage further?
Is there a way to debug exactly what's happening during TLS socket creation that's causing the ENOMEM error?
Should I be implementing a different approach for TLS on this device?

Parents Reply Children
No Data
Related