mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 17:31:11 -10:00
smb2: allocate nothing at all when no SMB server is configured
The pool-locking commit created the backend's bootstrap mutex whenever the configuration was published, whether or not SMB would ever be used: one allocation at startup on every HAVE_SMBCLIENT build. Remove even that. Intent is precisely expressible: SMB connections use only the configured server address - never the host embedded in an smb:// URL - so a publication carrying no server address means SMB cannot function this session and needs nothing. smb_init_cfg() now creates the bootstrap lock only when the published configuration carries a server address. A session with no SMB server configured performs a pointer store and a handful of scalar copies per publication and allocates exactly nothing: no mutex, no slot locks, no contexts, no sockets. Every publication site runs on the main thread (startup, configuration loads, and now saves), so gated lock creation stays race-free, and the happens-before argument for the slot locks is unchanged: operations reach a slot lock only through a handle, handles only exist after initialization, and initialization runs under the pool lock. The one flow that needs care is configuring a server through the menu mid-session. The menu writes land in settings->arrays, which the published struct aliases, so the backend can see a server address that no publication has carried yet - and without a publication there is no lock to serialize on. Operations refuse in that state with a message saying a configuration save activates SMB, and config_save_file() now publishes on success exactly like config_load_file() does: the menu flow reaches a save (manual or the default save-on-exit), which both refreshes the numeric snapshot and creates the bootstrap lock. Before the pool-locking work this same flow only half-worked anyway - the frozen numeric snapshot meant a mid-session server ran with fallback values until a republication - so the save requirement aligns activation with the point where the settings become correct at all. Verified offline before commit: the sanitizer harness gains scenarios asserting the zero-footprint contract behaviourally - a publication with an empty server sets up nothing and every operation refuses with zero connection attempts; a server visible only through the aliased strings still refuses until a publication carries it, then works after one does. Full battery clean: ASan+UBSan+LSan and TSan, single- and multi-threaded with heal chaos, zero contexts and handles alive after shutdown. Full Makefile build with --enable-builtinsmbclient and threads, settings table drift check and griffin-order unity compile all clean.
This commit is contained in:
1 parent
3c7447d9d0
commit
cea330ebe2
2 files changed
+40
-8
No files matched your search
@@ -9004,6 +9004,18 @@ bool config_save_file(const char *path)
|
||||
if (path_settings)
|
||||
free(path_settings);
|
||||
|
||||
#ifdef HAVE_SMBCLIENT
|
||||
/* Publish the SMB client settings on save as well as on load. This
|
||||
* is what lets SMB configured through the menu take effect in the
|
||||
* same session: the menu flow reaches a save (manual or
|
||||
* save-on-exit) and the publication both refreshes the numeric
|
||||
* snapshot and, now that a server address is configured, creates
|
||||
* the backend's bootstrap lock. A configuration with no server
|
||||
* address publishes for free - no lock, no allocation. */
|
||||
if (ret)
|
||||
retroarch_smb_init();
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -219,14 +219,23 @@ static struct smb2_context *smb_slot_heal_if_dead(unsigned slot,
|
||||
bool smb_init_cfg(const struct smb_settings *new_cfg)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
/* First publication happens on the main thread during startup,
|
||||
* before any thread can reach an smb:// path; see the pool
|
||||
* comment. Only the bootstrap pool lock is created here - one
|
||||
* mutex, whether or not SMB is ever used. The per-slot locks are
|
||||
* created under the pool lock on first actual SMB use, sized to
|
||||
* the configured pool, so a build that never touches an smb://
|
||||
* path never allocates them. */
|
||||
if (!smb_pool_lock && !(smb_pool_lock = slock_new()))
|
||||
/* Publications happen on the main thread (startup, configuration
|
||||
* loads and saves); see the pool comment. The bootstrap pool lock
|
||||
* is created only once a publication carries a configured server
|
||||
* address: SMB connections use only the configured server - never
|
||||
* the host embedded in an smb:// URL - so with no server
|
||||
* configured SMB cannot function this session and needs nothing.
|
||||
* A session with no intention of using SMB therefore allocates
|
||||
* exactly nothing here. Configuring a server in the menu takes
|
||||
* effect at the next publication, which the menu flow reaches by
|
||||
* saving the configuration (manually or via save-on-exit); the
|
||||
* per-slot locks are created later still, under the pool lock on
|
||||
* first actual smb:// access, sized to the configured pool. */
|
||||
if ( new_cfg
|
||||
&& new_cfg->server_address
|
||||
&& *new_cfg->server_address
|
||||
&& !smb_pool_lock
|
||||
&& !(smb_pool_lock = slock_new()))
|
||||
return false;
|
||||
#endif
|
||||
smb_cfg = new_cfg;
|
||||
@@ -263,7 +272,18 @@ static bool smb_init(void)
|
||||
bool ok = true;
|
||||
|
||||
if (!SMB_LOCKS_READY())
|
||||
{
|
||||
/* A server address is visible through the aliased configuration
|
||||
* strings but no publication has carried it yet: the SMB
|
||||
* settings were changed after the last configuration load.
|
||||
* They take effect at the next publication (configuration save
|
||||
* or load). */
|
||||
if (smb_cfg && smb_cfg->server_address && *smb_cfg->server_address)
|
||||
fprintf(stderr,
|
||||
"smb_init: SMB configured after startup; save the "
|
||||
"configuration to activate it\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
SMB_POOL_LOCK();
|
||||
|
||||
|
||||
Reference in new issue
Block a user