Application Lifecycle and Startup Flow¶
Overview¶
Movian follows a carefully orchestrated startup sequence that initializes components in dependency order, loads plugins, and prepares the user interface. This document details the complete application lifecycle from startup to shutdown.
Startup Sequence¶
Phase 1: Core Initialization (main_init())¶
graph TD
A[Application Start] --> B[Parse Command Line]
B --> C[Initialize Global Config]
C --> D[Unicode & Property System]
D --> E[Callout Framework]
E --> F[Network Layer Early Init]
F --> G[Logging System]
G --> H[Settings System]
H --> I[Notifications]
I --> J[Create Cache/Persistent Paths]
J --> K[Database Init]
K --> L[Blob Cache]
L --> M[Metadata System]
M --> N[Keyring]
N --> O[LibAV Init]
O --> P[Graphics Init Group]
P --> Q[GLW Settings]
Q --> R[Media Subsystem]
R --> S[Service Registry]
S --> T[Backend Handlers]
T --> U[Navigator Init]
U --> V[Audio System]
V --> W[Plugin Manager]
W --> X[Device ID Generation]
X --> Y[Software Update Thread]
Y --> Z[I18N System]
Z --> AA[Video Settings]
AA --> BB[IPC Init Group]
BB --> CC[Service Discovery]
CC --> DD[API Init Group]
DD --> EE[Async I/O Start]
EE --> FF[Run Control]
Detailed Initialization Steps¶
1. Basic Setup (main.c:main_init() lines 380-400)
// Initialize mutexes and global state
hts_mutex_init(&gconf.state_mutex);
hts_cond_init(&gconf.state_cond, &gconf.state_mutex);
gconf.exit_code = 1;
// Unicode and text processing
unicode_init();
// Property tree - core data model
prop_init();
init_global_info();
2. Network and Logging (lines 400-420)
// Callout framework for delayed execution
callout_init();
// Early network initialization
asyncio_init_early();
init_group(INIT_GROUP_NET);
// Logging system
trace_init();
prop_init_late();
3. Core Services (lines 420-460)
// Settings management
settings_init();
// Notification system
notifications_init();
// Create required directories
if(gconf.cache_path != NULL &&
fa_makedirs(gconf.cache_path, errbuf, sizeof(errbuf))) {
// Handle cache path creation failure
}
// Database initialization
#if ENABLE_SQLITE
db_init();
#endif
// Blob cache for efficient data storage
blobcache_init();
4. Media and Plugin Systems (lines 460-520)
// Metadata handling
#if ENABLE_METADATA
metadata_init();
metadb_init();
decoration_init();
#endif
// Subtitle system
subtitles_init();
// Security keyring
keyring_init();
// LibAV codec library
#if ENABLE_LIBAV
av_lockmgr_register(fflockmgr);
av_log_set_callback(fflog);
av_register_all();
#endif
// Graphics initialization group
init_group(INIT_GROUP_GRAPHICS);
// GLW UI settings
#if ENABLE_GLW
glw_settings_init();
#endif
// Media subsystem
media_init();
// Service handling
service_init();
// Backend content handlers
backend_init();
// Navigator for page management
nav_init();
// Audio subsystem
audio_init();
// Plugin manager
#if ENABLE_PLUGINS
plugins_init(gconf.devplugins);
#endif
Phase 2: Background Services¶
Software Update Thread (main.c:swthread() lines 150-220)
static void *swthread(void *aux)
{
#if ENABLE_PLUGINS
// Initialize plugin system phase 2
plugins_init2();
#endif
// Upgrade system initialization
upgrade_init();
usage_start();
if(!gconf.disable_upgrades) {
// Plugin repository updates (with retries)
#if ENABLE_PLUGINS
for(int i = 0; i < 10; i++) {
if(!plugins_upgrade_check())
break;
navigator_can_start(); // Signal navigator ready
sleep(i + 1);
}
#endif
// Application upgrade checks
for(int i = 0; i < 10; i++) {
if(!upgrade_refresh())
break;
sleep(i + 1);
}
} else {
navigator_can_start();
}
// Load site news and updates
load_site_news();
// Continuous update loop (12-hour intervals)
// ... periodic update logic
}
Phase 3: Plugin Loading (plugins.c)¶
Plugin Discovery (plugins_init() lines 1200-1250)
void plugins_init(char **devplugs)
{
// Initialize plugin view settings
plugins_view_settings_init();
hts_mutex_init(&plugin_mutex);
plugins_setup_root_props();
// Load development plugins if specified
if(devplugs != NULL) {
for(; (path = *devplugs) != NULL; devplugs++) {
if(plugin_load(path, errbuf, sizeof(errbuf),
PLUGIN_LOAD_FORCE | PLUGIN_LOAD_DEBUG)) {
TRACE(TRACE_ERROR, "plugins", "Unable to load dev plugin: %s", path);
}
}
}
}
Installed Plugin Loading (plugins_init2() lines 1180-1190)
void plugins_init2(void)
{
hts_mutex_lock(&plugin_mutex);
plugin_load_installed(); // Load from installedplugins/ directory
hts_mutex_unlock(&plugin_mutex);
}
Phase 4: Navigation System (navigator.c)¶
Navigator Initialization (nav_init() lines 320-340)
void nav_init(void)
{
#if ENABLE_BOOKMARKS
bookmarks_init();
#endif
prop_t *navs = prop_create(prop_get_global(), "navigators");
all_navigators = prop_create(navs, "nodes");
prop_linkselected_create(all_navigators, navs, "current", NULL);
}
Navigator Creation (nav_create() lines 240-320)
static navigator_t *nav_create(void)
{
navigator_t *nav = calloc(1, sizeof(navigator_t));
// Initialize page queues
TAILQ_INIT(&nav->nav_pages);
TAILQ_INIT(&nav->nav_history);
// Create property structure
nav->nav_prop_root = prop_create(all_navigators, NULL);
nav->nav_prop_pages = prop_create(nav->nav_prop_root, "pages");
nav->nav_prop_curpage = prop_create(nav->nav_prop_root, "currentpage");
// Set up event handling
nav->nav_eventsink = prop_subscribe(0,
PROP_TAG_CALLBACK_EVENT, nav_eventsink, nav,
PROP_TAG_MUTEX, &nav_mutex,
PROP_TAG_ROOT, eventsink, NULL);
// Open home page
nav_open0(nav, NAV_HOME, NULL, NULL, NULL, NULL, NULL);
return nav;
}
Runtime Operation¶
Page Navigation Flow¶
sequenceDiagram
participant User
participant Navigator
participant Backend
participant Plugin
participant GLW
User->>Navigator: Open URL
Navigator->>Navigator: Create nav_page_t
Navigator->>Backend: backend_open()
Backend->>Plugin: Plugin handler (if applicable)
Plugin->>Backend: Content/UI data
Backend->>Navigator: Page content ready
Navigator->>GLW: Update current page
GLW->>User: Render new content
Service Registration Flow¶
sequenceDiagram
participant Service
participant Registry
participant Properties
participant Settings
Service->>Registry: service_create()
Registry->>Properties: Create service properties
Registry->>Settings: Register settings (if managed)
Registry->>Registry: Add to service list
Registry->>Properties: Update global service tree
Plugin Loading Process¶
graph TD
A[Plugin ZIP File] --> B[Extract plugin.json]
B --> C[Parse Manifest]
C --> D[Validate Plugin ID]
D --> E[Check Dependencies]
E --> F[Load Plugin Code]
F --> G{Plugin Type?}
G -->|ECMAScript| H[Load JavaScript]
G -->|Views| I[Register View Files]
G -->|Native| J[Load Native Code]
H --> K[Initialize Plugin]
I --> K
J --> K
K --> L[Register Services]
L --> M[Plugin Ready]
Shutdown Sequence¶
Graceful Shutdown (app_shutdown())¶
graph TD
A[Shutdown Request] --> B[Set Exit Code]
B --> C[Start Shutdown Thread]
C --> D[Send ACTION_STOP Event]
D --> E[Flush Caches]
E --> F[Call arch_stop_req()]
F --> G{Arch Response?}
G -->|PROGRESSING| H[Wait for Completion]
G -->|NOT_HANDLED| I[Continue Shutdown]
G -->|CALLER_MUST_HANDLE| J[Call main_fini()]
H --> K[Monitor Progress]
I --> J
J --> L[arch_exit()]
Component Finalization (main_fini())¶
Shutdown Order (main.c:main_fini() lines 680-720)
void main_fini(void)
{
// Early shutdown hooks
shutdown_hook_run(1);
// Destroy popup system
prop_destroy_by_name(prop_get_global(), "popups");
// Finalize initialization groups in reverse order
fini_group(INIT_GROUP_API);
fini_group(INIT_GROUP_IPC);
// Shutdown major subsystems
#if ENABLE_PLAYQUEUE
playqueue_fini();
#endif
audio_fini();
nav_fini();
backend_fini();
// Late shutdown hooks
shutdown_hook_run(0);
// Final cleanup
blobcache_fini();
#if ENABLE_METADATA
metadb_fini();
#endif
kvstore_fini();
notifications_fini();
htsmsg_store_flush();
trace_fini();
}
Initialization Groups¶
Movian uses initialization groups to manage component dependencies:
INIT_GROUP_NET (Network Layer)¶
- Basic networking setup
- Socket initialization
- Protocol handlers
INIT_GROUP_GRAPHICS (Graphics System)¶
- Onavigatortext setup
- GLW initialization
- Platform-specific graphics
INIT_GROUP_IPC (Inter-Process Communication)¶
- D-Bus integration (Linux)
- Platform messaging systems
- External API interfaces
INIT_GROUP_API (External APIs)¶
- Web services integration
- Third-party API clients
- Remote service connections
Error Handling and Recovery¶
Startup Failures¶
- Critical Errors: Immediate exit with error code
- Non-Critical Errors: Continue with reduced functionality
- Resource Failures: Fallback to alternative paths
- Plugin Errors: Skip problematic plugins, continue startup
Runtime Error Recovery¶
- Service Failures: Automatic service restart
- Plugin Crashes: Plugin isolation and recovery
- Network Issues: Retry mechanisms and offline mode
- Memory Issues: Garbage collection and cache cleanup
Performance Considerations¶
Startup Optimization¶
- Lazy Loading: Defer non-critical initialization
- Parallel Initialization: Independent components start concurrently
- Cache Warming: Pre-load frequently used resources
- Plugin Prioritization: Load essential plugins first
Memory Management¶
- Reference Counting: Property system memory tracking
- Pool Allocation: Efficient memory allocation patterns
- Cache Limits: Bounded cache sizes with LRU eviction
- Plugin Isolation: Separate memory spaces for plugins
This lifecycle ensures reliable startup, stable operation, and clean shutdown while maintaining the flexibility to handle various error conditions and platform-specific requirements.lifecycleProperty systemReference CountingcomponentsAPIAPIsAPIGLWOpenGLcomponentinitialization groupsInitialization Groups