GUI application hangs (forever) if heavy thread starts in parallel lazarus / 31-LCL ---------------------------------------------------------------------- Dmitry24 · 2016-07-02 11:37 Unfortunately I encountered a strange problem when heavy thread is started programmatically at startup in parallel to main application. Application window sometimes stops responding at all (even button is not drawn). The only solution found is to start thread on timer and with the timer interval large enough. However it seems unreliable solution. The later thread starts the rarer the problem happen (but no guarantee it disappears at all for a certain interval). In most of examples threads are usually started on button clicks that is some time after form creation so that examples are not affected. The problems never happens while debugging. If the thread gives timeslices (e.g. threadswitch or even there is no heavy loop) there is no problem. Below is the example application where several points were tried to start the thread. The only workaround for me is to start inside the timer with interval of 200 ms (20 ms is not enough) or to start manually with button or to use threadswitch inside the thread for time slices. Otherwise window may hangs (however not always). Please give any advice... Lazarus 1.6 64-bit compiled in DEBUG mode and run on Ubuntu 14 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,  StdCtrls, ExtCtrls; type   { TForm1 }   TForm1 = class(TForm)    Button1: TButton;    Timer1: TTimer;    procedure Button1Click(Sender: TObject);    procedure FormCreate(Sender: TObject);    procedure Idle(Sender: TObject; var Done: boolean);    procedure Timer1Timer(Sender: TObject);  private    threadcreated: boolean;    { private declarations }  public    { public declarations }  end; var  Form1: TForm1; implementation {$R *.lfm} const  appTerminate: boolean = false; type    TThread1 = class(TThread)    protected      procedure Execute; override;    public      Constructor Create(CreateSuspended : boolean);    end;   constructor TThread1.Create(CreateSuspended : boolean);  begin    FreeOnTerminate := True;    inherited Create(CreateSuspended);  end;   procedure TThread1.Execute;  var    i, j: integer;  begin    j:=0;    for i:=0 to 200000000 do begin      j:=j+1;      //if (j and $FFFF=0) then threadswitch;    end;    appTerminate:=true;  end; { TForm1 } procedure TForm1.Button1Click(Sender: TObject);begin  //TThread1.Create(false);end; procedure TForm1.Idle(Sender: TObject; var Done: boolean);begin  if (appTerminate) then begin    Application.Terminate;    exit;  end;   Done:=true;   if (threadcreated) then exit;  //threadcreated:=true; TThread1.Create(false);end; procedure TForm1.Timer1Timer(Sender: TObject);begin  if (threadcreated) then exit;  //threadcreated:=true; TThread1.Create(false);end; procedure TForm1.FormCreate(Sender: TObject);begin  threadcreated:=false;  Application.OnIdle:={$IFDEF FPC}@{$ENDIF}Idle;  threadcreated:=true; TThread1.Create(false);end; end.  program project1; {$mode objfpc}{$H+} uses  {$IFDEF UNIX}  cthreads, cmem,  {$ENDIF}  Interfaces, // this includes the LCL widgetset  Forms, Unit1  { you can add units after this }; {$R *.res} begin  RequireDerivedFormResource:=True;  Application.Initialize;  Application.CreateForm(TForm1, Form1);  Application.Run;end.    Finally, it is found that even the following app freezes sometimes when run not from IDE (for those who does not read the rest). Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     program project1;         {$mode objfpc}{$H+}         uses      Interfaces, // this includes the LCL widgetset      Forms;         {$R *.res}       var      Form1: TForm;    begin      Application.Initialize;      Application.CreateForm(TForm, Form1);      Application.Run;    end. ---------------------------------------------------------------------- rvk · 2016-07-04 14:05 I can't reproduce this in virtualbox with Ubuntu 16 with the given source. I do have a small note about the {$IFDEF FPC}@{$ENDIF} use. If you use {$MODE DELPHI} this will not work correctly (@ shouldn't be used while FPC is still defined). You could use Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Application.OnIdle:={$IFNDEF FPC_DELPHI}@{$ENDIF}Idle; or if the source also needs to be compiled in Delphi: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Application.OnIdle:={$IFDEF FPC}{$IFNDEF FPC_DELPHI}@{$ENDIF}{$ENDIF}Idle; ---------------------------------------------------------------------- Dmitry24 · 2016-07-04 15:23 Thank you for responding. Thank you for the note. {$mode objfpc} directive is on the second line. Idle may be simply removed. Sometimes app freezes on startup (empty not responding window appears, sometimes buttons is drawn but also not responding). The second thread always completes successfully. If the second thread interacts with the main thread it also freezes. Even with 200 ms delay it sometimes freezes, and almost always without a delay, in release mode too. The same on Ubuntu 16 in Vmware. Additionally I found it freezes rarely when run from GUI file panel (Files) and almost always freezes when run from terminal. Additionally it seems never freezing when I run using sudo. It seems there is no problem with 32-bit compiled app, only with 64-bit. Could you sent the compiled app to make sure it is not a wrong compilation? How to attach a big file? ---------------------------------------------------------------------- rvk · 2016-07-04 16:15 Quote from: Dmitry24 on July 04, 2016, 05:23:45 pmThank you for the note. {$mode objfpc} directive is on the second line. Idle may be simply removed.In case you use objfpc you could have omitted the {$IFDEF FPC} completely. Normally this is done for using same source in Delphi. But if used in FPC you could have mode Delphi at the top in which case the IFDEFs I gave were more appropriate. (but indeed, for this test-case they are not necessary). QuoteAdditionally I found it freezes rarely when run from GUI file panel (Files) and almost always freezes when run from terminal. Additionally it seems never freezing when I run using sudo.Yes, I have it now too. It always works in the IDE. But I have it just the other way around. It seems to ALWAYS work if I run from terminal. But sometimes freezes (after 3 or 4 tries) when run from the file- explorer  You can't attach binaries here on the site (only small zip-files for sourcecode). Attached is my test-project and a temporary dropbox-link to the project1 executable: https://www.dropbox.com/s/4fhyrmujuki9qlc/project1.zip?dl=0 ---------------------------------------------------------------------- rvk · 2016-07-04 16:26 Additionally the problem might be in the way you terminate the program. Have you tried a loop of 800000000. When I do that it always works. The program has sufficient time to complete the creation of the Form1. When you have a small loop the thread is ending really soon and if the form isn't drawn yet (because of the busy thread) you terminate the program too soon. Does increasing the loop work for you? If that doesn't work... what happens if you just comment out the Application.Terminate ? ---------------------------------------------------------------------- Dmitry24 · 2016-07-04 17:00 Historically I write for FPC mode objfpc and for Delphi so there are such defines. Quote from: rvk on July 04, 2016, 06:15:57 pmYes, I have it now too. It always works in the IDE. Yes, I wrote the problems never happens while debugging. I mean in IDE it never happens. QuoteBut I have it just the other way around. It seems to ALWAYS work if I run from terminal. But sometimes freezes (after 3 or 4 tries) when run from the file-explorer  Sometimes it works from terminal many times in a row for me. QuoteYou can't attach binaries here on the site (only small zip-files for sourcecode). Thant you, it seems it is not necessary since the problem reproduced. QuoteAdditionally the problem might be in the way you terminate the program. I tried without auto terminating at all (it was just for simplicity of testing). It freezes anyway. Example is below Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,  StdCtrls, ExtCtrls; type   { TForm1 }   TForm1 = class(TForm)    Button1: TButton;    procedure Button1Click(Sender: TObject);    procedure FormCreate(Sender: TObject);  private    { private declarations }  public    { public declarations }  end; var  Form1: TForm1; implementation {$R *.lfm} type    TThread1 = class(TThread)  protected      procedure Execute; override;    public      Constructor Create(CreateSuspended : boolean);    end;   constructor TThread1.Create(CreateSuspended : boolean);  begin    FreeOnTerminate := True;    inherited Create(CreateSuspended);  end;   procedure TThread1.Execute;  var    i, j: integer;  begin    j:=0;    for i:=0 to 200000000 do begin      j:=j+1;      //if (j and $FFFF=0) then threadswitch; <- giving time slices helps    end;  end; { TForm1 } procedure TForm1.Button1Click(Sender: TObject);begin  TThread1.Create(false);end; procedure TForm1.FormCreate(Sender: TObject);begin  TThread1.Create(false);end; end.  Increasing loop does not help me (just checked again). Are you sure it really always helps you? Main thread freezes during the loop in the second thread. I spent two days searching bug in my big multithreaded application... And finally reduced it to an example above I need to make some startup quite heavy calculations just after the form is created. ---------------------------------------------------------------------- rvk · 2016-07-04 18:43 Quote from: Dmitry24 on July 04, 2016, 07:00:30 pmSometimes it works from terminal many times in a row for me. Ok, finally after doing 25 times ./project1, enter, alt_f4, up, enter, alt_f4, up, enter, alt_f4 I finally had it hang on terminal too. But via the file-explorer it usually hangs the 1st through 4th time. I've tried some things (dummy thread-initialization, CheckSynchronize()) but couldn't pin down why this would happen. But this goes beyond my ability to debug. Even removing FreeOnTerminate and doing this makes it hang: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.FormCreate(Sender: TObject);var  t :TThread1;begin  t := TThread1.Create(false);  t.WaitFor;  t.Free;end;In that case your thread is already ended when the form resumes creating. It still hangs with a blank form. (So I'm wondering if it's really your "busy" thread that's at fault or something else. Even this makes it hang after enough times (so without running a thread): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.FormCreate(Sender: TObject);var  t :TThread1;begin  //t := TThread1.Create(false);  //t.WaitFor;  //t.Free;end;So it might be just a general problem which the thread makes worse. Edit: Even starting a form with one button without the cthreads in the uses of the project, the project hangs after about 25 starts from the file-explorer. Edit #2: Now even after 1 or 2 starts. Seems like 64bit Lazarus is really unstable. Simple example of a button starting the same executable and exiting. Press the button a few times and see it hang. (How does it work for you?) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,  StdCtrls, ExtCtrls; type   { TForm1 }   TForm1 = class(TForm)    Button1: TButton;    procedure Button1Click(Sender: TObject);    procedure FormCreate(Sender: TObject);  private    { private declarations }  public    { public declarations }  end; var  Form1: TForm1; implementationuses Process; {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject);var  AProcess: TProcess;begin  AProcess := TProcess.Create(nil);  AProcess.Executable:= ParamStr(0);  AProcess.Execute;  AProcess.Free;  Close;end; procedure TForm1.FormCreate(Sender: TObject);beginend; end. ---------------------------------------------------------------------- Dmitry24 · 2016-07-05 05:54 Yes, a few times with TProcess (more often from File Explorer). Finally, I removed everything and still was able to get freeze several times for the app: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program project1; {$mode objfpc}{$H+} uses  Interfaces, // this includes the LCL widgetset  Forms; {$R *.res} var  Form1: TForm;begin  Application.Initialize;  Application.CreateForm(TForm, Form1);  Application.Run;end.  I don't know if all Uses are necessary for freeze because I had success (freeze) only two times for this app. Now I can't get freezing any more for such simple app regardless the number of retries. It seems some delay at startup may cause the freeze. A heavy thread or other circumstances may give such a delay. Currently I continue testing and can't get freeze anymore for anyone of apps... So sometimes the problem may dissappear at all on a system and is not reproducible  After reloading the system the problem appears again even for the simplest app. I removed unnecessary Uses (updated the example) and still sometimes it freezes. ---------------------------------------------------------------------- User137 · 2016-07-05 07:35 Making a few changes in code, marked with comments (not testing, not sure if helps): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,  StdCtrls, ExtCtrls; type   { TForm1 }   TForm1 = class(TForm)    Button1: TButton;    Timer1: TTimer;    procedure Button1Click(Sender: TObject);    procedure FormCreate(Sender: TObject);    procedure Idle(Sender: TObject; var Done: boolean);    procedure Timer1Timer(Sender: TObject);  private    threadcreated: boolean;    { private declarations }  public    { public declarations }  end; var  Form1: TForm1; implementation {$R *.lfm} const  appTerminate: boolean = false; type    TThread1 = class(TThread)    protected      procedure Execute; override;    public      Constructor Create(CreateSuspended : boolean);    end;   constructor TThread1.Create(CreateSuspended : boolean);  begin    inherited Create(CreateSuspended); // Normally inherit parent constructor first    FreeOnTerminate := True;    //inherited Create(CreateSuspended);  end;   procedure TThread1.Execute;  var    i, j: integer;  begin    j:=0;    //for i:=0 to 200000000 do begin    for i:=0 to 200 do begin // Test with smaller value first, does it freeze?      j:=j+1;      //if (j and $FFFF=0) then threadswitch;    end;    appTerminate:=true;  end; { TForm1 } procedure TForm1.Button1Click(Sender: TObject);begin  //TThread1.Create(false);end; procedure TForm1.Idle(Sender: TObject; var Done: boolean);begin  Done:=true; // Set first, otherwise it will remain false when it terminates  if (appTerminate) then begin    appTerminate:=false; // Just making sure it won't do this again, it's idle event afterall, who knows how often it's called    Application.Terminate;    exit;  end;   //Done:=true;   if (threadcreated) then exit;  //threadcreated:=true; TThread1.Create(false);end; procedure TForm1.Timer1Timer(Sender: TObject);begin  if (threadcreated) then exit;  //threadcreated:=true; TThread1.Create(false);end; procedure TForm1.FormCreate(Sender: TObject);begin  threadcreated:=false;  Application.OnIdle:={$IFDEF FPC}@{$ENDIF}Idle;  threadcreated:=true; TThread1.Create(false);end; end.  program project1; {$mode objfpc}{$H+} uses  {$IFDEF UNIX}  cthreads, cmem,  {$ENDIF}  Interfaces, // this includes the LCL widgetset  Forms, Unit1  { you can add units after this }; {$R *.res} begin  RequireDerivedFormResource:=True;  Application.Initialize;  Application.CreateForm(TForm1, Form1);  Application.Run;end. ---------------------------------------------------------------------- Dmitry24 · 2016-07-05 08:41 Please, read the previous message just before your answer... What changes could you suggest to the code above? ---------------------------------------------------------------------- rvk · 2016-07-05 13:01 I tried the original (with thread) on Mint and it worked fine (no hangs). Reinstalled Ubuntu and Lazarus (with fpclazup) and again... after a few starts it hangs. Not sure if that's because Ubuntu is way heavier than Mint, and consequently uses more resources which makes it hang, but either way... it shouldn't happen. I wouldn't be comfortable with releasing a 64bit version of software which "might" hang unexpectedly. Edit: yep. even an empty project with one button will hang if started repeatedly (sometimes after 4 or 5 tries, sometimes after much much more, like 50 tries but it eventually hangs). ---------------------------------------------------------------------- Cyrax · 2016-07-05 16:02 Can you guys check if Lazarus trunk and FPC trunk have same problem? Please disable any optimization options, too. ---------------------------------------------------------------------- rvk · 2016-07-05 19:41 O, I thought I tried trunk first but apparently that was for something else. After some trouble with fpclazup I managed to install trunk. First, with startlazarus, lazarus hanged a few times on the splash screen but finally I got it going. But unfortunately, trunk had the same result. The simple TProcess/run_by_button example hangs after about 8 runs. What did you mean by "disable any optimization options"? In FPC/Lazarus during compile or in Ubuntu (VM)? ---------------------------------------------------------------------- Cyrax · 2016-07-06 00:30 By disabling any optimization settings I mean compiling FPC, Lazarus and test program with "-O-"  option. ---------------------------------------------------------------------- fpcoder · 2016-07-06 02:59 FWIW, with no changes I compiled rvk's thread.zip project with Laz trunk and release fpc 3.0 under Ubuntu 16.04 - 64 bits. The application always starts and finishes, no matter if it starts from terminal, filemanager or Run from Lazarus. ---------------------------------------------------------------------- Dmitry24 · 2017-02-16 06:38 Still have the same issue with Lazarus 1.6.2  [The simplest 64-bit Linux app hangs at startup from time to time] ---------------------------------------------------------------------- balazsszekely · 2017-02-17 05:44 Did you try to create the thread suspended and let the GUI finish initializing. Start/resume the thread after that,  use a timer or another mechanism to achieve this. ---------------------------------------------------------------------- Dmitry24 · 2017-02-17 06:13 With periodical thread switching (if uncomment threadswitch line) it almost never hangs. Actually even the default blank application may hang (as was written above) but very very rarely. With heavy thread the effect is almost always when run the app from command line [now using Ubuntu 16.0 x64 on Vmware]. I attached to the frozen app and got stack traces. Maybe this may help somehow. Thread 1 Quote#0 syscall at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38 #1 ?? at :0 #2 g_dbus_connection_send_message_with_reply at :0 #3 ?? at :0 #4 g_dbus_connection_call at :0 #5 ?? at :0 #6 ?? at :0 #7 g_initable_new_valist at :0 #8 g_initable_new at :0 #9 gvfs_dbus_mount_tracker_proxy_new_for_bus_sync at :0 #10 ?? at :0 #11 ?? at :0 #12 g_type_create_instance at :0 #13 ?? at :0 #14 g_object_newv at :0 #15 g_object_new at :0 #16 ?? at :0 #17 ?? at :0 #18 g_file_new_for_path at :0 #19 ?? at :0 #20 g_type_create_instance at :0 #21 ?? at :0 #22 ?? at :0 #23 ?? at :0 #24 g_object_new_valist at :0 #25 g_object_new at :0 #26 ibus_bus_new_async at :0 #27 ?? at :0 #28 g_type_class_ref at :0 #29 g_object_newv at :0 #30 g_object_new at :0 #31 ibus_im_context_new at :0 #32 ?? at :0 #33 ?? at :0 #34 ?? at :0 #35 RESETDEFAULTIMCONTEXT at gtk2/gtk2globals.pp:422 #36 GTKFOCUSCB(0x172e360, 0x177f6e0, 0x17deef8) at gtk2/gtk2callback.inc:1038 #37 GTK2FOCUSCB(0x172e360, 0x177f6e0, 0x17dbfb8) at gtk2/gtk2widgetset.inc:54 #38 ?? at :0 #39 g_closure_invoke at :0 #40 ?? at :0 #41 g_signal_emit_valist at :0 #42 g_signal_emit at :0 #43 ?? at :0 #44 gtk_main_do_event at :0 #45 ?? at :0 #46 g_main_context_dispatch at :0 #47 ?? at :0 #48 g_main_context_iteration at :0 #49 gtk_main_iteration_do at :0 #50 APPPROCESSMESSAGES(0x16b05a8) at gtk2/gtk2widgetset.inc:2318 #51 HANDLEMESSAGE(0x16ae378) at include/application.inc:1262 #52 RUNLOOP(0x16ae378) at include/application.inc:1399 #53 APPRUN(0x16b05a8, {Proc = {procedure (POINTER)} 0x7ffd4333b350, Self = 0x16ae378}) at include/interfacebase.inc:54 #54 RUN(0x16ae378) at include/application.inc:1387 #55 main at project1.lpr:19 Thread 2 Quote#0 poll at ../sysdeps/unix/syscall-template.S:84 #1 ?? at :0 #2 g_main_context_iteration at :0 #3 ?? at :0 #4 ?? at :0 #5 start_thread(0x7f63c9058700) at pthread_create.c:333 #6 clone at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109 Thread 3 Quote#0 poll at ../sysdeps/unix/syscall-template.S:84 #1 ?? at :0 #2 g_main_context_iteration at :0 #3 ?? at :0 #4 ?? at :0 #5 start_thread(0x7f63c8857700) at pthread_create.c:333 #6 clone at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109 Thread 4 Quote#0 __lll_lock_wait at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135 #1 __GI___pthread_mutex_lock(0x16c7f90) at ../nptl/pthread_mutex_lock.c:115 #2 g_type_class_ref at :0 #3 g_object_newv at :0 #4 g_object_new at :0 #5 ?? at :0 #6 ?? at :0 #7 ?? at :0 #8 ?? at :0 #9 ?? at :0 #10 ?? at :0 #11 ?? at :0 #12 g_main_context_dispatch at :0 #13 ?? at :0 #14 g_main_loop_run at :0 #15 ?? at :0 #16 ?? at :0 #17 start_thread(0x7f63c3fff700) at pthread_create.c:333 #18 clone at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109 For thread 1 there may be different functions between #0 syscall and g_type_create_instance at :0 but others are the same between runs. ---------------------------------------------------------------------- AlexVas · 2017-06-14 02:35 Hi, I have the same issue running Ubuntu 16.04.2 LTS in a VirtualBox on iMac Retina 2016. It hangs reliably. Our testers reported the issue too. Just wondering if there are any known workarounds? I am stuck. Thank you.