static void delete_context(SMBCCTX *ctx) { //Trying to fix the error: no talloc stackframe at ../source3/libsmb/cliconnect.c:2637, leaking memory //TALLOC_CTX *frame = talloc_stackframe(); //First we need to purge the cache of servers the context has. //This should also free all the used memory allocations. smbc_getFunctionPurgeCachedServers(ctx)(ctx); //We're done with the frame, free it up now. //TALLOC_FREE(frame); //Next we need to free the context itself, and free all the //memory it used. smbc_free_context(ctx, 1); }
/* * Free a context * * Returns 0 on success. Otherwise returns 1, the SMBCCTX is _not_ freed * and thus you'll be leaking memory if not handled properly. * */ int smbc_free_context(SMBCCTX *context, int shutdown_ctx) { if (!context) { errno = EBADF; return 1; } if (shutdown_ctx) { SMBCFILE * f; DEBUG(1,("Performing aggressive shutdown.\n")); f = context->internal->files; while (f) { smbc_getFunctionClose(context)(context, f); f = f->next; } context->internal->files = NULL; /* First try to remove the servers the nice way. */ if (smbc_getFunctionPurgeCachedServers(context)(context)) { SMBCSRV * s; SMBCSRV * next; DEBUG(1, ("Could not purge all servers, " "Nice way shutdown failed.\n")); s = context->internal->servers; while (s) { DEBUG(1, ("Forced shutdown: %p (fd=%d)\n", s, s->cli->fd)); cli_shutdown(s->cli); smbc_getFunctionRemoveCachedServer(context)(context, s); next = s->next; DLIST_REMOVE(context->internal->servers, s); SAFE_FREE(s); s = next; } context->internal->servers = NULL; } } else { /* This is the polite way */ if (smbc_getFunctionPurgeCachedServers(context)(context)) { DEBUG(1, ("Could not purge all servers, " "free_context failed.\n")); errno = EBUSY; return 1; } if (context->internal->servers) { DEBUG(1, ("Active servers in context, " "free_context failed.\n")); errno = EBUSY; return 1; } if (context->internal->files) { DEBUG(1, ("Active files in context, " "free_context failed.\n")); errno = EBUSY; return 1; } } /* Things we have to clean up */ free(smbc_getWorkgroup(context)); smbc_setWorkgroup(context, NULL); free(smbc_getNetbiosName(context)); smbc_setNetbiosName(context, NULL); free(smbc_getUser(context)); smbc_setUser(context, NULL); DEBUG(3, ("Context %p successfully freed\n", context)); /* Free any DFS auth context. */ TALLOC_FREE(context->internal->auth_info); SAFE_FREE(context->internal); 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) { initialized_ctx_count--; } if (initialized_ctx_count == 0) { SMBC_module_terminate(); } /* Unlock the mutex */ if (SMB_THREAD_UNLOCK(initialized_ctx_count_mutex) != 0) { smb_panic("error unlocking 'initialized_ctx_count'"); } return 0; }
/* * Free a context * * Returns 0 on success. Otherwise returns 1, the SMBCCTX is _not_ freed * and thus you'll be leaking memory if not handled properly. * */ int smbc_free_context(SMBCCTX *context, int shutdown_ctx) { if (!context) { errno = EBADF; return 1; } if (shutdown_ctx) { SMBCFILE * f; DEBUG(1,("Performing aggressive shutdown.\n")); f = context->internal->files; while (f) { smbc_getFunctionClose(context)(context, f); f = f->next; } context->internal->files = NULL; /* First try to remove the servers the nice way. */ if (smbc_getFunctionPurgeCachedServers(context)(context)) { SMBCSRV * s; SMBCSRV * next; DEBUG(1, ("Could not purge all servers, " "Nice way shutdown failed.\n")); s = context->internal->servers; while (s) { DEBUG(1, ("Forced shutdown: %p (fd=%d)\n", s, s->cli->fd)); cli_shutdown(s->cli); smbc_getFunctionRemoveCachedServer(context)(context, s); next = s->next; DLIST_REMOVE(context->internal->servers, s); SAFE_FREE(s); s = next; } context->internal->servers = NULL; } } else { /* This is the polite way */ if (smbc_getFunctionPurgeCachedServers(context)(context)) { DEBUG(1, ("Could not purge all servers, " "free_context failed.\n")); errno = EBUSY; return 1; } if (context->internal->servers) { DEBUG(1, ("Active servers in context, " "free_context failed.\n")); errno = EBUSY; return 1; } if (context->internal->files) { DEBUG(1, ("Active files in context, " "free_context failed.\n")); errno = EBUSY; return 1; } } /* Things we have to clean up */ free(smbc_getWorkgroup(context)); smbc_setWorkgroup(context, NULL); free(smbc_getNetbiosName(context)); smbc_setNetbiosName(context, NULL); free(smbc_getUser(context)); smbc_setUser(context, NULL); DEBUG(3, ("Context %p successfully freed\n", context)); SAFE_FREE(context->internal); SAFE_FREE(context); if (initialized_ctx_count) { initialized_ctx_count--; } if (initialized_ctx_count == 0 && SMBC_initialized) { gencache_shutdown(); secrets_shutdown(); gfree_all(); SMBC_initialized = false; } return 0; }