Issue Details (XML | Word | Printable)

Key: CORE-3646
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Alexander Peshkov
Reporter: Pumuqui
Votes: 0
Watchers: 4
Operations

If you were logged in you would be able to see more operations.
Firebird Core

Segmentation fault in FreePascal multi-threaded program when using 2.5.x client library on Linux

Created: 28/Oct/11 06:30 AM   Updated: 23/Apr/13 01:23 PM
Component/s: API / Client Library
Affects Version/s: 2.5.0, 2.5.1
Fix Version/s: 2.5.2, 3.0 Alpha 1

Time Tracking:
Not Specified

Environment: OpenSuse 10.2 64 bits, Ubuntu 11.10 64-bits, FreePascal 2.2.5 x86_64, FreePascal 2.4.5 x86_64, Firebird 2.5.0, Firebird 2.5.1

Planning Status: Unspecified


 Description  « Hide
Segmentation fault for a FreePascal program,
that connects to a FB 2.5 database inside a thread.
The segmentation fault just occurs, when there is a
Firebird exception caught inside the thread.

The example code below should illustrate the situation.

There are no problems on Windows, nor on Linux when using
a 2.1 client library, the fault just happens for Linux and the 2.5 client.

I posted the error first on the fpc-devel list, where they told me that
this should be an error in the Firebird client dll:
http://www.mail-archive.com/fpc-devel@lists.freepascal.org/msg24051.html

Change the connection string in the following code, so that it points
to an existing database, then put the code into file fbthreadtest.lpr and compile with
<code>
fpc -gl -dUseCThreads -ofbthreadtest fbthreadtest.lpr
<code>

Run with
<code>
foo@PSERVER:~/Development/src$./fbthreadtest
select...
...exception
Violación de segmento
</code>

This is the example program:
<code>
program fbthreadtest;
{$IFDEF FPC}
  {$MODE DELPHI}{$H+}
{$ENDIF}

{$APPTYPE CONSOLE}
{$LINKLIB pthread}

uses
  {$IFDEF UNIX}
  cthreads,
  cwstring,
  {$ENDIF}
  Classes,
  IBConnection, sqldb;

type
  TFBThread = class(TThread)
  private
  protected
    procedure Execute; override;
  public
    constructor Create;
  end;

constructor TFBThread.Create;
begin
  inherited Create(True);
  FreeOnTerminate := False;
  Resume;
end;

procedure TFBThread.Execute;
var
  db: TIBConnection;
  tr: TSQLTransaction;
  q: TSQLQuery;
begin
  db := TIBConnection.Create(nil);
  try
    db.DatabaseName := 'localhost:/home/data/Database/ssstst.gdb';
    db.LoginPrompt := False;
    db.HostName := '';
    db.UserName := 'SYSDBA';
    db.Password := 'masterkey';
    db.Connected := TRUE;
    tr := TSQLTransaction.Create(nil);
    try
      tr.DataBase := db;
      tr.Action := caCommit;
      tr.Params.Clear;
      tr.Params.Add('isc_tpb_read_committed');
      tr.Params.Add('isc_tpb_rec_version');
      tr.Params.Add('isc_tpb_nowait');
      db.Transaction := tr;
      tr.Active := True;
      q := TSQLQuery.Create(nil);
      try
        q.Database := db;
        q.Transaction := tr;

        try
          Writeln('select...');
          // the following line raises an exception because rdb$databases
doesn't exist.
          q.SQL.Text := 'select count(*) from rdb$databases';
          q.Prepare;
        except
          Writeln('...exception');
        end;
      finally
        q.Free;
      end;
    finally
      tr.Commit;
      tr.Free;
    end;
  finally
    db.Connected := False;
    db.Free;
  end;
end;

begin
  with TFBThread.Create do begin
    WaitFor;
    Free;
  end;
end.
</code>


 All   Comments   Work Log   Change History   Version Control   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Alexander Peshkov added a comment - 31/Oct/11 06:39 PM
Thread's destructor function does not behave exactly according to POSIX standard on linux. After destroying associated key function is anyway attempted to be called when thread terminates, which (taken together with aleready unloaded client library) causes segfault. Solution is to use windows-like approach, where we never used thread dtor at all.

Alexander Peshkov added a comment - 29/Dec/11 09:48 AM
Unfortunately linux (glibc) implementation of pthread_kill() function is unstable and can segfault in case of invalid thread id. Better solution is required here.