Skip to content

Code quality improvements, CERALIVE fork migration, and documentation restructure#5

Merged
andrescera merged 19 commits intomainfrom
docs/improve-documentation-structure
Jan 9, 2026
Merged

Code quality improvements, CERALIVE fork migration, and documentation restructure#5
andrescera merged 19 commits intomainfrom
docs/improve-documentation-structure

Conversation

@andrescera
Copy link
Copy Markdown
Member

@andrescera andrescera commented Jan 9, 2026

Overview

This PR brings belacoder up to quality standards with comprehensive fixes to signal handling, error handling, resource management, and documentation. It also migrates all references to use CERALIVE forks (srt, srtla, belacoder).


Code Quality Improvements (belacoder.c)

🔒 Signal Handling Safety

  • Async-signal-safe SIGHUP: Use volatile sig_atomic_t reload_bitrate_flag instead of calling unsafe functions from signal handler
  • GLib signal integration: Use g_unix_signal_add() for SIGTERM/SIGINT to properly integrate with GLib main loop

⚠️ Error Handling

  • SRT socket options: Replace assert() with proper if checks and fprintf(stderr, ...) error messages
  • String parsing: New parse_long() helper with full errno, endptr, and range validation
  • SRT version check: Compile-time #error if SRT < 1.4.0 (required for SRTO_RETRANSMITALGO)

🧹 Resource Management

  • SRT cleanup: Add srt_cleanup() at end of main
  • File cleanup: Add munmap() for pipeline file and close() for file descriptor

📐 Code Quality

  • Named constants: Extract magic numbers to #define (EMA_SLOW, RTT_MIN_DRIFT, BS_TH3_MULT, etc.)
  • Type-safe macros: Use GLib MIN()/MAX() instead of custom macros (prevents double evaluation)
  • POSIX compliance: Use CLOCK_MONOTONIC instead of Linux-specific CLOCK_MONOTONIC_RAW
  • Modern APIs: Replace deprecated usleep() with nanosleep()
  • Overflow prevention: Use int64_t for bitrate calculations
  • Consistent logging: Standardize to fprintf(stderr, ...)
  • Portability: Add missing includes (<signal.h>, <time.h>, etc.)

Build System

Dockerfile

  • Updated to clone and build from CERALIVE/srt fork
  • Fixed cmake build commands (out-of-source build)

Documentation

Repository References Updated

  • BELABOX/srtCERALIVE/srt
  • BELABOX/srtlaCERALIVE/srtla
  • BELABOX/belacoderCERALIVE/belacoder

Network Bonding

  • Added comprehensive srtla integration documentation to README
  • Added network bonding section to architecture.md
  • Configuration tips for different deployment scenarios

Moved Proposals to GitHub Issues

Deleted Doc Issue
docs/code-quality-and-risks.md #2 - Future Improvements
docs/balancing-algorithms.md #3 - Multi-Algorithm Support
docs/rust-go-migration-feasibility.md #4 - Rust Migration

Final Documentation Structure

docs/
├── architecture.md    # System overview + network bonding
├── bitrate-control.md # Algorithm specification
└── dependencies.md    # Build requirements

Commits (19 total)

Type Description
fix Async-signal-safe SIGHUP handler
fix g_unix_signal_add for SIGTERM/SIGINT
fix srt_cleanup() at end of main
fix Clean up pipeline fd and mmap
fix Replace assert() with error handling
fix CLOCK_MONOTONIC (POSIX)
fix Add missing includes
fix SRT version compile-time check
fix nanosleep() instead of usleep()
fix GLib MIN/MAX macros
refactor Named constants for magic numbers
fix Proper strtol error handling
fix int64_t for bitrate calculations
refactor Standardize stderr logging
docs Update docs with code fixes
fix Forward declaration fix
build Dockerfile uses CERALIVE/srt
docs Restructure and update references

Related Issues

The previous implementation called read_bitrate_file() directly from
signal context, which invoked non-async-signal-safe functions (fopen,
getline, malloc, free). This could cause deadlocks or corruption.

Changes:
- Add volatile sig_atomic_t flag for signal communication
- Add minimal sighup_handler() that only sets the flag
- Check flag in stall_check() to reload bitrate file safely
- Fix file handle leak in read_bitrate_file() (missing fclose)
- Remove unsafe cast to __sighandler_t

Fixes Critical Issue #1 and Low Issue #13 from code-quality-and-risks.md
The previous implementation called stop() directly from signal context,
which invoked g_main_loop_quit() - not async-signal-safe. While GLib
tries to handle this, it's technically undefined behavior.

Changes:
- Add stop_from_signal() GLib callback wrapper
- Use g_unix_signal_add() instead of raw signal()
- Signals are now handled safely from the GLib main loop

Fixes High Issue #5 from code-quality-and-risks.md
srt_startup() was called but srt_cleanup() was never called. This
leaks SRT library resources. While not critical for a single-run
process, this could cause issues if the code is embedded or run
multiple times.

Fixes High Issue #2 from code-quality-and-risks.md
The pipeline file descriptor was never closed and the mmap region was
never munmapped. This caused minor resource leaks.

Changes:
- Close pipeline_fd immediately after mmap (mmap keeps its own reference)
- Also close fd on empty file error path
- Rename 'len' to 'launch_string_len' for clarity and proper type (size_t)
- Add munmap() call at program exit

Fixes High Issue #3 from code-quality-and-risks.md
Using assert() for runtime errors is problematic: in release builds
(NDEBUG), checks are removed entirely and failures silently proceed
with incorrect socket configuration.

Changes:
- Replace all assert(ret == 0) after srt_setsockflag with proper checks
- Print descriptive error messages using srt_getlasterror_str()
- Return -4 error code for socket option failures
- Add -4 case to error reason switch in main()
- For SRTO_PEERLATENCY getter, just warn instead of failing (non-critical)

Fixes High Issue #4 from code-quality-and-risks.md
CLOCK_MONOTONIC_RAW is Linux-specific. Use POSIX-compliant
CLOCK_MONOTONIC for better portability (macOS, BSD).

Also:
- Replace assert() with proper error handling
- Fix potential integer overflow in nanosecond division
- Rename variable to 'ts' for clarity

Fixes Medium Issue #11 from code-quality-and-risks.md
Add explicit includes for functions used:
- <arpa/inet.h> for inet_addr()
- <errno.h> for errno (needed for strtol error handling)
- <time.h> for nanosleep() (upcoming fix)

Previously worked via transitive includes, but this is fragile.

Fixes Low Issue #12 from code-quality-and-risks.md
belacoder uses SRTO_RETRANSMITALGO which requires SRT 1.4.0 or later.
Add a compile-time check to provide a clear error message instead of
confusing compile or link errors with older SRT versions.

Fixes Low Issue #15 from code-quality-and-risks.md
usleep() was deprecated in POSIX.1-2008. Use nanosleep() instead
for better portability and standards compliance.

Fixes Low Issue #16 from code-quality-and-risks.md
Custom min/max macros evaluated arguments multiple times, which could
cause bugs if arguments have side effects (e.g., min(++x, y)).

GLib's MIN/MAX macros are properly implemented to avoid this issue.
Keep lowercase aliases for compatibility with existing code.

Fixes Medium Issue #7 from code-quality-and-risks.md
Replace hardcoded numeric values with named constants to improve
code readability and make tuning easier.

New constant groups:
- EMA_* for exponential moving average smoothing factors
- RTT_* for RTT tracking parameters
- BS_TH* for buffer size threshold multipliers

This makes the bitrate control algorithm easier to understand and
allows tuning parameters to be adjusted in one place.

Fixes Medium Issue #8 from code-quality-and-risks.md
strtol returns 0 on failure which could be confused with valid input.
The endptr was ignored, so trailing garbage like "500000abc" was
silently accepted.

Changes:
- Add parse_long() helper with full error checking
- Check errno for overflow/underflow
- Validate endptr to reject trailing garbage
- Allow trailing whitespace/newline (for file parsing)
- Range checking built into the helper
- Update parse_bitrate(), parse_ip_port(), and CLI parsing

Fixes Medium Issue #9 from code-quality-and-risks.md
At maximum bitrate (30 Mbps), calculations are safe with int, but if
ABS_MAX_BITRATE is increased, overflow could occur. Use int64_t for
intermediate calculations.

Also:
- Track previous rounded bitrate to avoid redundant encoder updates
- Cleaner separation between calculation and update logic

Fixes Medium Issue #10 from code-quality-and-risks.md
Replace g_print() and printf() with fprintf(stderr, ...) for consistent
logging. Only version output (-v) remains on stdout as that's the
expected behavior for version queries.

Fixes Low Issue #17 from code-quality-and-risks.md
- Update code-quality-and-risks.md to mark all fixed issues
- Update bitrate-control.md to reference new named constants
- Add new documentation files:
  - architecture.md - System overview
  - dependencies.md - Build and runtime requirements
  - balancing-algorithms.md - Alternative algorithm designs
  - rust-go-migration-feasibility.md - Language migration analysis

All 14 code issues (1 critical, 4 high, 5 medium, 4 low) have been fixed.
2 issues remain deferred for future structural refactoring.
- architecture.md: Add sections on signal handling and resource management
- README.md: Note that SRT 1.4.0+ is enforced at compile time
- dependencies.md: Document compile-time SRT version check
- Add forward declaration for read_bitrate_file() to fix implicit
  declaration warning when called from stall_check()
- Add gpointer parameter to connection_housekeeping() to match
  GSourceFunc signature expected by g_timeout_add()
- Switch from IRLServer/srt to CERALIVE/srt (the recommended fork)
- Fix cmake build commands (use out-of-source build)
- Remove obsolete branch checkout (master is correct)
- Update all repository references to CERALIVE (srt, srtla, belacoder)
- Add network bonding section to README and architecture docs
- Move proposal docs to GitHub issues:
  - code-quality-and-risks.md → Issue #2
  - balancing-algorithms.md → Issue #3
  - rust-go-migration-feasibility.md → Issue #4
- Clean up stale cross-references in remaining docs
- Keep only actual documentation (architecture, bitrate-control, dependencies)
@andrescera andrescera changed the title docs: improve documentation structure and update references feat: code quality improvements and documentation restructure Jan 9, 2026
@andrescera andrescera changed the title feat: code quality improvements and documentation restructure Code quality improvements, CERALIVE fork migration, and documentation restructure Jan 9, 2026
@andrescera andrescera merged commit 3f58d48 into main Jan 9, 2026
andrescera added a commit that referenced this pull request Jan 9, 2026
The previous implementation called stop() directly from signal context,
which invoked g_main_loop_quit() - not async-signal-safe. While GLib
tries to handle this, it's technically undefined behavior.

Changes:
- Add stop_from_signal() GLib callback wrapper
- Use g_unix_signal_add() instead of raw signal()
- Signals are now handled safely from the GLib main loop

Fixes High Issue #5 from code-quality-and-risks.md
@andrescera andrescera deleted the docs/improve-documentation-structure branch January 9, 2026 23:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant