Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unixodbc not unloading dynamic libraries when calling SQLDisconnect #643

Open
amountainram opened this issue Nov 11, 2024 · 2 comments
Open

Comments

@amountainram
Copy link

Hi,

I've an application which acts as job runner: it schedules and executes task which in turn use odbc-api to connect to a SQL DB via the respective driver.

The connect/fetch/disconnect parts of my routines successfully run. For the sake of example this may be a job:

 fn run<'a>(
        &'a mut self,
        id: JobId,
        _ctx: RunnerContext<'a>,
    ) -> futures::future::BoxFuture<'a, mayflower_core::Result<()>> {
        let conn = self
            .odbc_env
            .connect_with_connection_string(
                &self.connection_string,
                odbc_api::ConnectionOptions::default(),
            )
            .unwrap();

        println!(
            "job_id: {id}, name: {}",
            conn.database_management_system_name().unwrap()
        );

        conn.into_handle().disconnect().unwrap();

        ready(Ok(())).boxed()
    }

The odbc env is an odbc_api::Environment which is shared across the whole application as a singleton as suggested in the documentation.

Since my application runs different jobs and most of time may stay idle i'd like the dynamically loaded drivers to unload when all connections to that driver are disconnected and their handles dropped.

I've had a look to unixODBC source code and somehow here and thus here the driver should/could be unloaded from memory.

The snippet above ofc triggers loading of the driver but disconnecting and then dropping the conn handle does not do anything and drivers stay in resident memory.

Not even sure this a bug or an unhandled use case of this library, but I'm wondering whether I'm using incorrectly the handles or am I misunderstanding the underlying unixODBC library.

Thanks in advance for any comment on this issue

@amountainram
Copy link
Author

I've forgot to mention that I've deactivated pooling both from library (default) and odbcinst.ini by setting

[ODBC]
Pooling=No

this is to ensure unixODBC does not keep the library loaded to make pooling faster

@pacman82
Copy link
Owner

Hello @amountainram ,

I am not sure under which, if any, circumstances unixODBC would unload a driver. Closing all the connections associated with that driver would certainly be a precondition. Seems to be some options around it, but I can not find any documentation outside of C headers. Best hint I got so far is here: https://github.com/lurcher/unixODBC/blob/93b0d9d5e7ecd5e1f62af05c3872c2173696ab27/DriverManager/SQLConnect.c#L1058

Ultimately it is up to the driver manager to load and maybe unload any symbols from dynamically linked memory. odbc-api can only tell the driver manager that the connection is not in use.

The odbc env is an odbc_api::Environment which is shared across the whole application as a singleton as suggested in the documentation.

That's a recommendation for a typical application. A typical application would also reuse the same driver over and over again with maybe even more than one connection in parallel. Your use-case seems different. Feel free to deviate from the recommendation. I would probably stick to ODBC environment at once and not roll the dice to hard, on how the drivers are implemented in C and how they use global state. odbc-apiis a safe abstraction over ODBC, but if there are bugs in the C driver, they may still invalidate your memory, and using ODBC drivers in unusual ways is a good way to find bugs. Not sure what drivers and how many of them you intend to use though. Multiple environments caused never trouble in my tests, with e.g. a Microsoft SQL Server, or something reasonably well written.

If it comes down to it, I can not answer your question whether unixODBC should free this memory and call dlclose. There seem to be some relevant options though in the mapping string.

Best, Markus

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

No branches or pull requests

2 participants