• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Step-by-Step: Diagnosing memory leaks and socket exhaustion in daemon processes on OVH Servers

Step-by-Step: Diagnosing memory leaks and socket exhaustion in daemon processes on OVH Servers

Identifying the Culprit: Initial System-Level Checks

When daemon processes on OVH servers exhibit erratic behavior, often manifesting as slow response times, unresponsiveness, or outright crashes, memory leaks and socket exhaustion are prime suspects. The first step is to establish a baseline and identify which processes are consuming excessive resources. We’ll leverage standard Linux utilities for this.

Begin by connecting to your OVH server via SSH and running a system-wide resource utilization check. The goal here is to pinpoint processes that are consistently consuming a disproportionately large amount of memory (RES or VIRT) or have an unusually high number of open file descriptors, which often correlates with open sockets.

Monitoring Memory Usage

We’ll use top and ps to get a snapshot of memory consumption. For a more sustained view, atop is invaluable as it logs historical data.

Using top for Real-time Analysis

Run top and sort by memory usage. Pay close attention to the %MEM and RES columns. RES (Resident Memory Size) is the non-swapped physical memory a task has used. A steadily increasing RES value for a specific daemon process over time is a strong indicator of a memory leak.

To sort by memory in top, press M after launching it. To exit, press q.

Using ps for Detailed Process Information

ps provides a static snapshot but can be more precise for scripting or specific process identification. We’ll look for the process ID (PID) of the suspect daemon and then query its memory usage.

First, find the PID of your daemon. Replace your_daemon_name with the actual name or a part of it.

pgrep -fl your_daemon_name

Once you have the PID (let’s assume it’s 12345), you can get detailed memory information:

ps aux | grep 12345

Focus on the %MEM and RSS (Resident Set Size, equivalent to RES in top) columns. For a more granular view, especially for virtual memory, use:

ps -p 12345 -o pid,ppid,cmd,%mem,rss,vsz

Leveraging atop for Historical Analysis

atop is a system and process monitor that logs system activity, including memory and disk usage, to a file (typically /var/log/atop/atop_YYYYMMDD). This is crucial for diagnosing intermittent issues or leaks that develop over hours or days.

If atop is not installed, install it:

sudo apt update && sudo apt install atop  # For Debian/Ubuntu
sudo yum install atop  # For CentOS/RHEL

To view historical data for a specific day, use:

atop -r /var/log/atop/atop_YYYYMMDD

Within the atop interface, press m to sort by memory usage. Look for processes whose memory consumption (RES) is steadily increasing over the logged period. You can navigate through time using the t (next) and T (previous) keys.

Diagnosing Socket Exhaustion

Socket exhaustion occurs when a process opens too many network connections (sockets) and exhausts the available file descriptors or ephemeral port range. This often leads to new connection failures and can impact the entire system’s networkability.

Checking Open File Descriptors

Every open socket is represented as a file descriptor. We can check the number of open file descriptors per process.

First, find the PID of your suspect daemon (e.g., 12345).

pgrep -fl your_daemon_name

Then, list the open file descriptors for that PID:

ls -l /proc/12345/fd | wc -l

A high number here, especially if it’s approaching the per-process limit (often 1024 by default, but configurable), indicates a potential issue. To see the actual limit for the process:

cat /proc/12345/limits | grep 'Max open files'

For a system-wide view of open file descriptors and their distribution across processes, lsof is powerful:

sudo lsof | awk '{ print $1 " " $2 " " $9 }' | sort | uniq -c | sort -nr | head -n 20

This command lists the top 20 processes by the number of open files. Look for your daemon process and check if it’s consistently at the top with a very high count.

Monitoring Network Sockets

netstat and ss are essential for examining network connections.

Using ss (which is generally faster and more efficient than netstat):

sudo ss -tunp | grep 'your_daemon_name'

This command shows TCP (t), UDP (u), and numeric (n) socket information, along with the process name (p) associated with each socket. Look for an excessive number of connections in states like ESTABLISHED, CLOSE_WAIT, or TIME_WAIT for your daemon.

To specifically count the number of connections for your daemon:

sudo ss -tunp | grep 'your_daemon_name' | wc -l

If this number is consistently high and growing, it points to socket exhaustion or a process that’s not properly closing connections.

Deep Dive: Profiling Memory Leaks

Once a suspected memory leak is identified, we need to understand *what* is being leaked. This often requires language-specific profiling tools.

PHP Memory Profiling with Xdebug

For PHP daemons (e.g., using Swoole, ReactPHP, or long-running CLI scripts), Xdebug can be configured to generate memory allocation profiles.

Ensure Xdebug is installed and configured in your php.ini. Key settings for memory profiling:

xdebug.mode = develop,debug,profile
xdebug.start_with_request = yes
xdebug.output_dir = /tmp/xdebug_profiles
xdebug.profiler_output_name = cachegrind.out.%s
xdebug.profiler_enable_trigger = 1

To trigger profiling for a specific request or script execution, you can use a cookie or environment variable. For CLI scripts, setting an environment variable is common:

XDEBUG_MODE=profile php your_daemon_script.php

This will generate a cachegrind.out.* file in the specified output directory. These files can be analyzed with tools like KCacheGrind (Linux) or WebGrind (web-based).

Alternatively, for more direct memory usage analysis within PHP, you can use functions like memory_get_usage() and memory_get_peak_usage() at various points in your code to track growth. For long-running processes, logging these values periodically can reveal the leak’s source.

// Example within a long-running PHP loop
$startTime = microtime(true);
$startMemory = memory_get_usage();

while (true) {
    // ... your daemon's work ...

    $currentTime = microtime(true);
    $currentMemory = memory_get_usage();
    $elapsedTime = $currentTime - $startTime;
    $memoryUsed = $currentMemory - $startMemory;

    if ($elapsedTime > 300) { // Log every 5 minutes
        error_log(sprintf("Daemon Stats: Time: %.2f s, Memory Used: %.2f MB", $elapsedTime, $memoryUsed / 1024 / 1024));
        $startTime = $currentTime;
        $startMemory = $currentMemory;
    }

    usleep(100000); // 100ms
}

Python Memory Profiling with objgraph and memory_profiler

For Python daemons, objgraph is excellent for visualizing object references, and memory_profiler can provide line-by-line memory usage.

Install them:

pip install objgraph memory_profiler

Using objgraph to find objects that are growing in count:

import objgraph
import gc

# Trigger garbage collection to get a clean state
gc.collect()

# Get a snapshot of object counts
initial_counts = objgraph.count_objects()

# ... run your code that might leak ...

# Trigger GC again
gc.collect()

# Get a new snapshot
final_counts = objgraph.count_objects()

# Find objects that have increased significantly
for obj_type, count in final_counts.items():
    initial_count = initial_counts.get(obj_type, 0)
    if count > initial_count * 1.5: # Example: 50% increase
        print(f"Object type {obj_type} increased from {initial_count} to {count}")
        # You can then use objgraph.show_most_common_types() or objgraph.show_backrefs()
        # to investigate further.
        # objgraph.show_backrefs(objgraph.by_type(obj_type)[0], max_depth=5, filename='backrefs.png')

Using memory_profiler for line-by-line analysis:

# Add this decorator to your functions
from memory_profiler import profile

@profile
def my_leaky_function():
    a = [1] * (10 ** 6)
    b = [2] * (2 * 10 ** 7)
    del b
    return a

if __name__ == '__main__':
    my_leaky_function()

Run this script with:

python -m memory_profiler your_script.py

Tuning System Limits and Process Behavior

Once the root cause is identified, you might need to adjust system limits or the daemon’s configuration.

Adjusting File Descriptor Limits

If socket exhaustion is due to legitimate high traffic, you may need to increase the maximum number of open file descriptors.

Edit /etc/security/limits.conf to set limits for specific users or groups. For example, to set the open files limit for the user running your daemon (e.g., www-data):

# /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536
www-data soft nofile 65536
www-data hard nofile 65536

You may also need to adjust system-wide limits in /etc/sysctl.conf, specifically fs.file-max:

# /etc/sysctl.conf
fs.file-max = 2097152

Apply these changes:

sudo sysctl -p

Remember that processes inherit limits from their parent. You might need to restart the daemon for new limits to take effect. For systemd services, limits can be set directly in the service unit file:

[Service]
LimitNOFILE=65536

Optimizing Daemon Configuration

Many daemons have configuration options to manage connection pooling, timeouts, and resource usage. For example:

  • Web Servers (Nginx/Apache): Adjust worker processes, keep-alive timeouts, and connection limits.
  • Database Proxies (e.g., ProxySQL): Tune connection pool sizes and query caching.
  • Application-specific Daemons: Review documentation for settings related to thread pools, buffer sizes, and garbage collection intervals.

For instance, in Nginx, you might adjust worker_connections and worker_rlimit_nofile.

# /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 4096; # Increase from default 1024
    multi_accept on;
}

http {
    # ... other http settings ...
}

# Ensure the user has sufficient limits, often set in /etc/security/limits.conf
# or via systemd service file as shown previously.
# You can also set worker_rlimit_nofile here if not managed elsewhere:
# worker_rlimit_nofile 65536;

Conclusion

Diagnosing memory leaks and socket exhaustion on OVH servers requires a systematic approach, starting with system-level monitoring and drilling down into process-specific behavior and language-level profiling. By combining tools like top, ps, atop, lsof, ss, and language-specific profilers, you can effectively pinpoint the root cause and implement the necessary tuning or code fixes to ensure your daemon processes run reliably.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Top 100 Developer Tooling and Productivity SaaS Ideas to Launch in 2026 to Boost Organic Search Growth by 200%
  • Top 100 Developer-Centric Code Snippet Managers and Customization Plugins to Double User Engagement and Session Duration
  • Top 5 API Monetization Frameworks and Gateway Strategies for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Premium Newsletter and Subscription Business Models for Devs for High-Traffic Technical Portals

Categories

  • apache (1)
  • Business & Monetization (380)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (484)
  • DevOps (7)
  • DevOps & Cloud Scaling (918)
  • Django (1)
  • Migration & Architecture (66)
  • MySQL (1)
  • Performance & Optimization (626)
  • PHP (5)
  • Plugins & Themes (90)
  • Security & Compliance (524)
  • SEO & Growth (425)
  • Server (23)
  • Ubuntu (9)
  • WordPress (22)
  • WordPress Plugin Development (7)

Recent Posts

  • Top 100 Developer Tooling and Productivity SaaS Ideas to Launch in 2026 to Boost Organic Search Growth by 200%
  • Top 100 Developer-Centric Code Snippet Managers and Customization Plugins to Double User Engagement and Session Duration
  • Top 5 API Monetization Frameworks and Gateway Strategies for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Premium Newsletter and Subscription Business Models for Devs for High-Traffic Technical Portals
  • Top 100 SEO and Schema Markup Plugins for Headless Decoupled Sites for Independent Web Developers and Indie Hackers

Top Categories

  • DevOps & Cloud Scaling (918)
  • Performance & Optimization (626)
  • Security & Compliance (524)
  • Debugging & Troubleshooting (484)
  • SEO & Growth (425)
  • Business & Monetization (380)

Our Products

  • School Management & Student Administration System
  • Integrated Hospital & Clinic Management System
  • Real Estate Directory & Agent Portal
  • Restaurant POS & Table Booking System
  • Retail Inventory POS & Billing System
  • Pharmacy Inventory & Clinic Billing System

Our Services

  • Vibe Engineering & AI Code Auditing Services
  • Prompt Engineering & "Vibe Coding" Workflow Consulting
  • AI-Augmented "Vibe Coding" & Rapid MVP Development
  • Figma to Shopify Liquid Theme Customization
  • Figma to WooCommerce Frontend Development
  • Figma to Magento 2 Theme Development

Copyright © 2026 · Vinay Vengala