Thread: Fix for ODBC close

Fix for ODBC close

From
Bruce Momjian
Date:
I have applied the following patch to properly exit ODBC.  I also
patched the ODBC makefile so it links under BSD/OS.  The -Bsymbolic
under BSD/OS is very harsh under BSD/OS, requiring all symbols even in
libc and crt1.o to be resolved before creating the shared library.

My 'ld' manual says:

       -Bsymbolic
              When  creating a shared library, bind references to
              global symbols to the definition within the  shared
              library,  if  any.   Normally, it is possible for a
              program linked against a shared library to override
              the definition within the shared library.  This op-
              tion is only meaningful on ELF platforms which sup-
              port shared libraries.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
Index: src/interfaces/odbc/GNUmakefile
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/GNUmakefile,v
retrieving revision 1.8
diff -c -r1.8 GNUmakefile
*** src/interfaces/odbc/GNUmakefile    2000/12/16 18:14:25    1.8
--- src/interfaces/odbc/GNUmakefile    2001/02/10 04:25:23
***************
*** 24,30 ****
          gpps.o tuple.o tuplelist.o dlg_specific.o $(OBJX)

  SHLIB_LINK = $(filter -lm, $(LIBS))
-
  all: all-lib

  # Shared library stuff
--- 24,29 ----
***************
*** 33,39 ****
--- 32,46 ----
  # Symbols must be resolved to the version in the shared library because
  # the driver manager (e.g., iodbc) provides some symbols with the same
  # names and we don't want those.  (This issue is probably ELF specific.)
+ #
+ # BSD/OS fails with libc and crt1.o undefined symbols without this.
+ # bjm 2001-02-09
+ #
+ ifneq ($(PORTNAME), bsdi)
  LINK.shared += $(shlib_symbolic)
+ endif

  odbc_headers = isql.h isqlext.h iodbc.h
  odbc_includedir = $(includedir)/iodbc
Index: src/interfaces/odbc/socket.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/socket.c,v
retrieving revision 1.7
diff -c -r1.7 socket.c
*** src/interfaces/odbc/socket.c    2000/05/27 03:35:14    1.7
--- src/interfaces/odbc/socket.c    2001/02/10 04:25:29
***************
*** 1,4 ****
-
  /* Module:          socket.c
   *
   * Description:     This module contains functions for low level socket
--- 1,3 ----
***************
*** 78,84 ****
--- 77,87 ----
  {
      if (self->socket != -1) {
          if ( ! shutdown(self->socket, 2)) /* no sends or receives */
+         {
+             SOCK_put_char(self, 'X');
+             SOCK_flush_output(self);
              closesocket(self->socket);
+         }
      }

      if (self->buffer_in)

Re: Fix for ODBC close

From
Peter Eisentraut
Date:
Bruce Momjian writes:

> I have applied the following patch to properly exit ODBC.  I also
> patched the ODBC makefile so it links under BSD/OS.  The -Bsymbolic
> under BSD/OS is very harsh under BSD/OS, requiring all symbols even in
> libc and crt1.o to be resolved before creating the shared library.

The -Bsymbolic switch is the same on all platforms that have it.  You can
link without it, but then you won't actually be able to use the ODBC
driver.  It seems like you need to link in a few other libraries to
resolve all symbols.

--
Peter Eisentraut      peter_e@gmx.net       http://yi.org/peter-e/


Re: Fix for ODBC close

From
Bruce Momjian
Date:
> Bruce Momjian writes:
>
> > I have applied the following patch to properly exit ODBC.  I also
> > patched the ODBC makefile so it links under BSD/OS.  The -Bsymbolic
> > under BSD/OS is very harsh under BSD/OS, requiring all symbols even in
> > libc and crt1.o to be resolved before creating the shared library.
>
> The -Bsymbolic switch is the same on all platforms that have it.  You can
> link without it, but then you won't actually be able to use the ODBC
> driver.  It seems like you need to link in a few other libraries to
> resolve all symbols.

OK, if this is true on all platforms, why isn't -lc needed?

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: [ODBC] Re: Fix for ODBC closeu

From
Bruce Momjian
Date:
> > Bruce Momjian writes:
> >
> > > I have applied the following patch to properly exit ODBC.  I also
> > > patched the ODBC makefile so it links under BSD/OS.  The -Bsymbolic
> > > under BSD/OS is very harsh under BSD/OS, requiring all symbols even in
> > > libc and crt1.o to be resolved before creating the shared library.
> >
> > The -Bsymbolic switch is the same on all platforms that have it.  You can
> > link without it, but then you won't actually be able to use the ODBC
> > driver.  It seems like you need to link in a few other libraries to
> > resolve all symbols.
>
> OK, if this is true on all platforms, why isn't -lc needed?
>

And if -lc is somehow done by default with ld -Bsymbolic, how do I deal
with a link that accesses crt1.o startup symbols, like environ and
__progname?


--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: [HACKERS] Re: [ODBC] Re: Fix for ODBC closeu

From
Bruce Momjian
Date:
> > > Bruce Momjian writes:
> > >
> > > > I have applied the following patch to properly exit ODBC.  I also
> > > > patched the ODBC makefile so it links under BSD/OS.  The -Bsymbolic
> > > > under BSD/OS is very harsh under BSD/OS, requiring all symbols even in
> > > > libc and crt1.o to be resolved before creating the shared library.
> > >
> > > The -Bsymbolic switch is the same on all platforms that have it.  You can
> > > link without it, but then you won't actually be able to use the ODBC
> > > driver.  It seems like you need to link in a few other libraries to
> > > resolve all symbols.
> >
> > OK, if this is true on all platforms, why isn't -lc needed?
> >
>
> And if -lc is somehow done by default with ld -Bsymbolic, how do I deal
> with a link that accesses crt1.o startup symbols, like environ and
> __progname?
>

OK, the following fixes the link on BSDI, while allowing -Bsymbolic.  I
have to explicitly include -R crt1.o to be used to resolve symbols, but
not to be linked in.  Without -R, I get undefined 'main' which makes
sense.

I am still confused why other OS's work, unless -lc is assumed by ld,
and their libc's have no crt1.o references.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
Index: src/interfaces/odbc/GNUmakefile
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/GNUmakefile,v
retrieving revision 1.9
diff -c -r1.9 GNUmakefile
*** src/interfaces/odbc/GNUmakefile    2001/02/10 05:50:27    1.9
--- src/interfaces/odbc/GNUmakefile    2001/02/10 11:26:13
***************
*** 36,43 ****
  # BSD/OS fails with libc and crt1.o undefined symbols without this.
  # bjm 2001-02-09
  #
- ifneq ($(PORTNAME), bsdi)
  LINK.shared += $(shlib_symbolic)
  endif

  odbc_headers = isql.h isqlext.h iodbc.h
--- 36,44 ----
  # BSD/OS fails with libc and crt1.o undefined symbols without this.
  # bjm 2001-02-09
  #
  LINK.shared += $(shlib_symbolic)
+ ifeq ($(PORTNAME), bsdi)
+ SHLIB_LINK += -lc -R /usr/lib/crt1.o
  endif

  odbc_headers = isql.h isqlext.h iodbc.h

Re: Fix for ODBC close

From
Peter Eisentraut
Date:
Bruce Momjian writes:

> > The -Bsymbolic switch is the same on all platforms that have it.  You can
> > link without it, but then you won't actually be able to use the ODBC
> > driver.  It seems like you need to link in a few other libraries to
> > resolve all symbols.
>
> OK, if this is true on all platforms, why isn't -lc needed?

Theory 1:  Many other platforms use the compiler driver ([g]cc) to link
shared libraries.  That makes all the right things happen.  Most likely
this should happen on a lot more platforms that currently use ld directly.

Theory 2:  Not many people have tried to build the ODBC driver on
non-mainstream platforms.

--
Peter Eisentraut      peter_e@gmx.net       http://yi.org/peter-e/


Re: [HACKERS] Re: Fix for ODBC close

From
Bruce Momjian
Date:
> Bruce Momjian writes:
>
> > > The -Bsymbolic switch is the same on all platforms that have it.  You can
> > > link without it, but then you won't actually be able to use the ODBC
> > > driver.  It seems like you need to link in a few other libraries to
> > > resolve all symbols.
> >
> > OK, if this is true on all platforms, why isn't -lc needed?
>
> Theory 1:  Many other platforms use the compiler driver ([g]cc) to link
> shared libraries.  That makes all the right things happen.  Most likely
> this should happen on a lot more platforms that currently use ld directly.
>
> Theory 2:  Not many people have tried to build the ODBC driver on
> non-mainstream platforms.

I just tried gcc and got:

#$ gcc -shared -soname libpsqlodbc.so.0 -Bsymbolic info.o bind.o
columninfo.o connection.o convert.o drvconn.o environ.o execute.o lobj.o
misc.o options.o pgtypes.o psqlodbc.o qresult.o results.o socket.o
parse.o statement.o gpps.o tuple.o tuplelist.o dlg_specific.o
-L/usr/local/lib -L/usr/contrib/lib -lm -o libpsqlodbc.so.0.26
gcc: unrecognized option `-soname'
gcc: file path prefix `symbolic' never used


--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: Fix for ODBC close

From
Nick Gorham
Date:
pgman@candle.pha.pa.us wrote:

> I have applied the following patch to properly exit ODBC.  I also
> patched the ODBC makefile so it links under BSD/OS.  The -Bsymbolic
> under BSD/OS is very harsh under BSD/OS, requiring all symbols even in
> libc and crt1.o to be resolved before creating the shared library.
>
> My 'ld' manual says:
>
>        -Bsymbolic
>               When  creating a shared library, bind references to
>               global symbols to the definition within the  shared
>               library,  if  any.   Normally, it is possible for a
>               program linked against a shared library to override
>               the definition within the shared library.  This op-
>               tion is only meaningful on ELF platforms which sup-
>               port shared libraries.

Hmm,

removing that may break it when running under a driver manager though...

I will check of FreeBSD, it certainly will on Linux ELF.

--
Nick Gorham
When I die, I want to go like my grandfather did, gently while sleeping,
and not like his passangers, screaming in a panic, looking for the
inflatable raft. -- Seen on ./




RE: Fix for ODBC close

From
Dave Page
Date:

> -----Original Message-----
> From: Bruce Momjian [mailto:pgman@candle.pha.pa.us]
> Sent: 10 February 2001 05:46
> To: PostgreSQL odbc list; PostgreSQL-patches
> Cc: PostgreSQL-development
> Subject: [PATCHES] Fix for ODBC close
>
>
> I have applied the following patch to properly exit ODBC.

<Snip>

I just compiled from the current cvs under win32 and I still get
'pq_recvbuf: unexpected EOF on client connection' when exiting apps using
the ODBC driver. I have tested with pgAdmin which uses ADO (ActiveX Data
Objects) and certainly closes the ADO connection object on exit, as well as
a simple test app using DAO (Data Access Objects). I did have a go at fixing
this myself when Bruce first mentioned it, and had exactly the same results
with similar code :-(

Regards,

Dave.

Re: [ODBC] RE: Fix for ODBC close

From
Bruce Momjian
Date:
OK, I have ifdef'ed out the sending of the 'X' parameter.  I will see if
placing it somewhere else will help.  Could it have to do with the fact
we are in a transaction in ODBC?  My guess is that the X is returning
data that is triggering the error.

[ Charset ISO-8859-1 unsupported, converting... ]
>
>
> > -----Original Message-----
> > From: Bruce Momjian [mailto:pgman@candle.pha.pa.us]
> > Sent: 10 February 2001 05:46
> > To: PostgreSQL odbc list; PostgreSQL-patches
> > Cc: PostgreSQL-development
> > Subject: [PATCHES] Fix for ODBC close
> >
> >
> > I have applied the following patch to properly exit ODBC.
>
> <Snip>
>
> I just compiled from the current cvs under win32 and I still get
> 'pq_recvbuf: unexpected EOF on client connection' when exiting apps using
> the ODBC driver. I have tested with pgAdmin which uses ADO (ActiveX Data
> Objects) and certainly closes the ADO connection object on exit, as well as
> a simple test app using DAO (Data Access Objects). I did have a go at fixing
> this myself when Bruce first mentioned it, and had exactly the same results
> with similar code :-(
>
> Regards,
>
> Dave.
>


--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: [ODBC] RE: Fix for ODBC close

From
Bruce Momjian
Date:
OK, I have a pretty good guess about the cause of the ODBC shutdown
failure message in the server logs.  Sending 'X' is still causing the
error message.

The error you are seeing is from the backend libpq code, the area that
communicates with clients.

So, let's assume the problem is not the platform, but the client code.
Libpq properly shuts connections without triggering that message.  ODBC
does trigger the message.

libpq closes connections with:

        (void) pqPuts("X", conn);
        (void) pqFlush(conn);

while ODBC closes with:

        SOCK_put_char(self, 'X');
        SOCK_flush_output(self);

They then close() the socket.

It seems the difference is in the flushing.  libpq has elaborate flush
code:

    while (len > 0)
    {
            sent = send(conn->sock, ptr, len, 0);
            len -= sent;

            if (pqWait(FALSE, TRUE, conn))
    }

and pqWait does:

        if (select(conn->sock + 1, &input_mask, &output_mask, (fd_set *) NULL,


For flush, ODBC does a simple:

    written = send(self->socket, (char *) self->buffer_out, self->buffer_filled_out, 0);


It seems we may need to add flush code similar to libpq in ODBC.

At a minimum, we have to put the send() in a loop and keep going until
there are no more bytes to send.  Not sure the select() is required.

Comments?

After I receive comments, I will prepare a patch people can test.


---------------------------------------------------------------------------



.  > OK, I have ifdef'ed out the sending of the 'X' parameter.  I will see if
> placing it somewhere else will help.  Could it have to do with the fact
> we are in a transaction in ODBC?  My guess is that the X is returning
> data that is triggering the error.
>
> [ Charset ISO-8859-1 unsupported, converting... ]
> >
> >
> > > -----Original Message-----
> > > From: Bruce Momjian [mailto:pgman@candle.pha.pa.us]
> > > Sent: 10 February 2001 05:46
> > > To: PostgreSQL odbc list; PostgreSQL-patches
> > > Cc: PostgreSQL-development
> > > Subject: [PATCHES] Fix for ODBC close
> > >
> > >
> > > I have applied the following patch to properly exit ODBC.
> >
> > <Snip>
> >
> > I just compiled from the current cvs under win32 and I still get
> > 'pq_recvbuf: unexpected EOF on client connection' when exiting apps using
> > the ODBC driver. I have tested with pgAdmin which uses ADO (ActiveX Data
> > Objects) and certainly closes the ADO connection object on exit, as well as
> > a simple test app using DAO (Data Access Objects). I did have a go at fixing
> > this myself when Bruce first mentioned it, and had exactly the same results
> > with similar code :-(
> >
> > Regards,
> >
> > Dave.
> >
>
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 853-3000
>   +  If your life is a hard drive,     |  830 Blythe Avenue
>   +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
>


--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

RE: [ODBC] RE: Fix for ODBC close

From
"Hiroshi Inoue"
Date:
> -----Original Message-----
> From: Bruce Momjian
>
> OK, I have a pretty good guess about the cause of the ODBC shutdown
> failure message in the server logs.  Sending 'X' is still causing the
> error message.
>
> The error you are seeing is from the backend libpq code, the area that
> communicates with clients.
>
> while ODBC closes with:
>
>         SOCK_put_char(self, 'X');
>         SOCK_flush_output(self);
>

Probably you have to put above code before calling
shutdown() not after.  shutdown(sock, 2) disables
both sends and receives on the socket.

Regards,
Hiroshi Inoue


Re: [ODBC] RE: Fix for ODBC close

From
Bruce Momjian
Date:
> > -----Original Message-----
> > From: Bruce Momjian
> >
> > OK, I have a pretty good guess about the cause of the ODBC shutdown
> > failure message in the server logs.  Sending 'X' is still causing the
> > error message.
> >
> > The error you are seeing is from the backend libpq code, the area that
> > communicates with clients.
> >
> > while ODBC closes with:
> >
> >         SOCK_put_char(self, 'X');
> >         SOCK_flush_output(self);
> >
>
> Probably you have to put above code before calling
> shutdown() not after.  shutdown(sock, 2) disables
> both sends and receives on the socket.

Thanks.  I was so focused on close() I never noticed the shutdown().
Can someone please test now?

Hiroshi, should I be concerned that a send() that does not send the full
packet just returns an error and does not retry?  Is libpq() so complex
because of async connections?

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: [HACKERS] Re: [ODBC] RE: Fix for ODBC close

From
Tom Lane
Date:
+               SOCK_put_char(self, 'X');
+               SOCK_flush_output(self);
+               if (!shutdown(self->socket, 2)) /* no sends or receives */
                        closesocket(self->socket);

I think you should issue the close() whether the shutdown() succeeds or
not.  Otherwise you have a file descriptor leak.  In fact, given that
you're going to close the socket, the separate shutdown call is a
complete waste of cycles.  Take it out.

> Hiroshi, should I be concerned that a send() that does not send the full
> packet just returns an error and does not retry?  Is libpq() so complex
> because of async connections?

Right, libpq only needs to loop because it runs the socket in nonblock
mode.  SOCK_flush_output looks OK to me.  (SOCK_get_next_byte, on the
other hand, goes wacko on error or close... probably should make it
return a null character instead of random data.)

            regards, tom lane

Re: [ODBC] RE: Fix for ODBC close

From
Hiroshi Inoue
Date:
Bruce Momjian wrote:
>
> > > -----Original Message-----
> > > From: Bruce Momjian
> > >
> > > OK, I have a pretty good guess about the cause of the ODBC shutdown
> > > failure message in the server logs.  Sending 'X' is still causing the
> > > error message.
> > >
> > > The error you are seeing is from the backend libpq code, the area that
> > > communicates with clients.
> > >
> > > while ODBC closes with:
> > >
> > >             SOCK_put_char(self, 'X');
> > >             SOCK_flush_output(self);
> > >
> >
> > Probably you have to put above code before calling
> > shutdown() not after.  shutdown(sock, 2) disables
> > both sends and receives on the socket.
>
> Thanks.  I was so focused on close() I never noticed the shutdown().
> Can someone please test now?
>

I had already tested it in win32 environment before
I posted my previous mail.

Regards,
Hiroshi Inoue