mirror of
https://github.com/samba-team/samba.git
synced 2025-03-10 12:58:35 +03:00
Thread-safe protection: libsmbclient initialization
- Begin converting init functions to use SMB_THREAD_ONCE. libsmbclient module-wide initialization is now moved into a separate function and called via SMB_THREAD_ONCE. - libsmbclient counts users (contexts) so that it can release global resources when the last context is closed. That count of contexts is now protected by a mutex. Derrell
This commit is contained in:
parent
045af600f2
commit
636fbd1028
@ -30,8 +30,112 @@
|
|||||||
/*
|
/*
|
||||||
* Is the logging working / configfile read ?
|
* Is the logging working / configfile read ?
|
||||||
*/
|
*/
|
||||||
static bool SMBC_initialized;
|
static bool SMBC_initialized = false;
|
||||||
static unsigned int initialized_ctx_count;
|
static unsigned int initialized_ctx_count = 0;
|
||||||
|
static void *initialized_ctx_count_mutex = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do some module- and library-wide intializations
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
SMBC_module_init(void * punused)
|
||||||
|
{
|
||||||
|
bool conf_loaded = False;
|
||||||
|
char *home = NULL;
|
||||||
|
TALLOC_CTX *frame = talloc_stackframe();
|
||||||
|
|
||||||
|
load_case_tables();
|
||||||
|
|
||||||
|
setup_logging("libsmbclient", True);
|
||||||
|
|
||||||
|
#if 0 /* need a place to put this (thread local storage) */
|
||||||
|
if (context->internal->debug_stderr) {
|
||||||
|
dbf = x_stderr;
|
||||||
|
x_setbuf(x_stderr, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Here we would open the smb.conf file if needed ... */
|
||||||
|
|
||||||
|
lp_set_in_client(True);
|
||||||
|
|
||||||
|
home = getenv("HOME");
|
||||||
|
if (home) {
|
||||||
|
char *conf = NULL;
|
||||||
|
if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) {
|
||||||
|
if (lp_load(conf, True, False, False, True)) {
|
||||||
|
conf_loaded = True;
|
||||||
|
} else {
|
||||||
|
DEBUG(5, ("Could not load config file: %s\n",
|
||||||
|
conf));
|
||||||
|
}
|
||||||
|
SAFE_FREE(conf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!conf_loaded) {
|
||||||
|
/*
|
||||||
|
* Well, if that failed, try the get_dyn_CONFIGFILE
|
||||||
|
* Which points to the standard locn, and if that
|
||||||
|
* fails, silently ignore it and use the internal
|
||||||
|
* defaults ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, False)) {
|
||||||
|
DEBUG(5, ("Could not load config file: %s\n",
|
||||||
|
get_dyn_CONFIGFILE()));
|
||||||
|
} else if (home) {
|
||||||
|
char *conf;
|
||||||
|
/*
|
||||||
|
* We loaded the global config file. Now lets
|
||||||
|
* load user-specific modifications to the
|
||||||
|
* global config.
|
||||||
|
*/
|
||||||
|
if (asprintf(&conf,
|
||||||
|
"%s/.smb/smb.conf.append",
|
||||||
|
home) > 0) {
|
||||||
|
if (!lp_load(conf, True, False, False, False)) {
|
||||||
|
DEBUG(10,
|
||||||
|
("Could not append config file: "
|
||||||
|
"%s\n",
|
||||||
|
conf));
|
||||||
|
}
|
||||||
|
SAFE_FREE(conf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
load_interfaces(); /* Load the list of interfaces ... */
|
||||||
|
|
||||||
|
reopen_logs(); /* Get logging working ... */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Block SIGPIPE (from lib/util_sock.c: write())
|
||||||
|
* It is not needed and should not stop execution
|
||||||
|
*/
|
||||||
|
BlockSignals(True, SIGPIPE);
|
||||||
|
|
||||||
|
/* Create the mutex we'll use to protect initialized_ctx_count */
|
||||||
|
if (SMB_THREAD_CREATE_MUTEX("initialized_ctx_count_mutex",
|
||||||
|
initialized_ctx_count_mutex) != 0) {
|
||||||
|
smb_panic("SMBC_module_init: "
|
||||||
|
"failed to create 'initialized_ctx_count' mutex");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TALLOC_FREE(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SMBC_module_terminate(void)
|
||||||
|
{
|
||||||
|
gencache_shutdown();
|
||||||
|
secrets_shutdown();
|
||||||
|
gfree_all();
|
||||||
|
SMBC_initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a new empty handle to fill in with your own info
|
* Get a new empty handle to fill in with your own info
|
||||||
@ -41,6 +145,9 @@ smbc_new_context(void)
|
|||||||
{
|
{
|
||||||
SMBCCTX *context;
|
SMBCCTX *context;
|
||||||
|
|
||||||
|
/* The first call to this function should initialize the module */
|
||||||
|
SMB_THREAD_ONCE(&SMBC_initialized, SMBC_module_init, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All newly added context fields should be placed in
|
* All newly added context fields should be placed in
|
||||||
* SMBC_internal_data, not directly in SMBCCTX.
|
* SMBC_internal_data, not directly in SMBCCTX.
|
||||||
@ -209,16 +316,24 @@ smbc_free_context(SMBCCTX *context,
|
|||||||
SAFE_FREE(context->internal);
|
SAFE_FREE(context->internal);
|
||||||
SAFE_FREE(context);
|
SAFE_FREE(context);
|
||||||
|
|
||||||
|
/* Protect access to the count of contexts in use */
|
||||||
|
if (SMB_THREAD_LOCK(initialized_ctx_count_mutex) != 0) {
|
||||||
|
smb_panic("error locking 'initialized_ctx_count'");
|
||||||
|
}
|
||||||
|
|
||||||
if (initialized_ctx_count) {
|
if (initialized_ctx_count) {
|
||||||
initialized_ctx_count--;
|
initialized_ctx_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (initialized_ctx_count == 0 && SMBC_initialized) {
|
if (initialized_ctx_count == 0) {
|
||||||
gencache_shutdown();
|
SMBC_module_terminate();
|
||||||
secrets_shutdown();
|
|
||||||
gfree_all();
|
|
||||||
SMBC_initialized = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unlock the mutex */
|
||||||
|
if (SMB_THREAD_UNLOCK(initialized_ctx_count_mutex) != 0) {
|
||||||
|
smb_panic("error unlocking 'initialized_ctx_count'");
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,7 +542,6 @@ smbc_init_context(SMBCCTX *context)
|
|||||||
{
|
{
|
||||||
int pid;
|
int pid;
|
||||||
char *user = NULL;
|
char *user = NULL;
|
||||||
char *home = NULL;
|
|
||||||
|
|
||||||
if (!context) {
|
if (!context) {
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
@ -449,88 +563,6 @@ smbc_init_context(SMBCCTX *context)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SMBC_initialized) {
|
|
||||||
/*
|
|
||||||
* Do some library-wide intializations the first time we get
|
|
||||||
* called
|
|
||||||
*/
|
|
||||||
bool conf_loaded = False;
|
|
||||||
TALLOC_CTX *frame = talloc_stackframe();
|
|
||||||
|
|
||||||
load_case_tables();
|
|
||||||
|
|
||||||
setup_logging("libsmbclient", True);
|
|
||||||
if (context->internal->debug_stderr) {
|
|
||||||
dbf = x_stderr;
|
|
||||||
x_setbuf(x_stderr, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Here we would open the smb.conf file if needed ... */
|
|
||||||
|
|
||||||
lp_set_in_client(True);
|
|
||||||
|
|
||||||
home = getenv("HOME");
|
|
||||||
if (home) {
|
|
||||||
char *conf = NULL;
|
|
||||||
if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) {
|
|
||||||
if (lp_load(conf, True, False, False, True)) {
|
|
||||||
conf_loaded = True;
|
|
||||||
} else {
|
|
||||||
DEBUG(5, ("Could not load config file: %s\n",
|
|
||||||
conf));
|
|
||||||
}
|
|
||||||
SAFE_FREE(conf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!conf_loaded) {
|
|
||||||
/*
|
|
||||||
* Well, if that failed, try the get_dyn_CONFIGFILE
|
|
||||||
* Which points to the standard locn, and if that
|
|
||||||
* fails, silently ignore it and use the internal
|
|
||||||
* defaults ...
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, False)) {
|
|
||||||
DEBUG(5, ("Could not load config file: %s\n",
|
|
||||||
get_dyn_CONFIGFILE()));
|
|
||||||
} else if (home) {
|
|
||||||
char *conf;
|
|
||||||
/*
|
|
||||||
* We loaded the global config file. Now lets
|
|
||||||
* load user-specific modifications to the
|
|
||||||
* global config.
|
|
||||||
*/
|
|
||||||
if (asprintf(&conf,
|
|
||||||
"%s/.smb/smb.conf.append",
|
|
||||||
home) > 0) {
|
|
||||||
if (!lp_load(conf, True, False, False, False)) {
|
|
||||||
DEBUG(10,
|
|
||||||
("Could not append config file: "
|
|
||||||
"%s\n",
|
|
||||||
conf));
|
|
||||||
}
|
|
||||||
SAFE_FREE(conf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
load_interfaces(); /* Load the list of interfaces ... */
|
|
||||||
|
|
||||||
reopen_logs(); /* Get logging working ... */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Block SIGPIPE (from lib/util_sock.c: write())
|
|
||||||
* It is not needed and should not stop execution
|
|
||||||
*/
|
|
||||||
BlockSignals(True, SIGPIPE);
|
|
||||||
|
|
||||||
/* Done with one-time initialisation */
|
|
||||||
SMBC_initialized = true;
|
|
||||||
|
|
||||||
TALLOC_FREE(frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!smbc_getUser(context)) {
|
if (!smbc_getUser(context)) {
|
||||||
/*
|
/*
|
||||||
* FIXME: Is this the best way to get the user info?
|
* FIXME: Is this the best way to get the user info?
|
||||||
@ -610,13 +642,20 @@ smbc_init_context(SMBCCTX *context)
|
|||||||
if (smbc_getTimeout(context) > 0 && smbc_getTimeout(context) < 1000)
|
if (smbc_getTimeout(context) > 0 && smbc_getTimeout(context) < 1000)
|
||||||
smbc_setTimeout(context, 1000);
|
smbc_setTimeout(context, 1000);
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: Should we check the function pointers here?
|
|
||||||
*/
|
|
||||||
|
|
||||||
context->internal->initialized = True;
|
context->internal->initialized = True;
|
||||||
|
|
||||||
|
/* Protect access to the count of contexts in use */
|
||||||
|
if (SMB_THREAD_LOCK(initialized_ctx_count_mutex) != 0) {
|
||||||
|
smb_panic("error locking 'initialized_ctx_count'");
|
||||||
|
}
|
||||||
|
|
||||||
initialized_ctx_count++;
|
initialized_ctx_count++;
|
||||||
|
|
||||||
|
/* Unlock the mutex */
|
||||||
|
if (SMB_THREAD_UNLOCK(initialized_ctx_count_mutex) != 0) {
|
||||||
|
smb_panic("error unlocking 'initialized_ctx_count'");
|
||||||
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user