Lazarus

Programming => General => Topic started by: xinyiman on October 18, 2020, 12:21:40 am

Title: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: xinyiman on October 18, 2020, 12:21:40 am
Hello everybody. I have a problem. I have a program that uses multithreading and within secondary threads it uses this procedure. On windows and mac os it doesn't work properly. On ubuntu instead it makes me crash the program. The line is that of the LoadFromDevice. Can anyone tell me why?
The procedure works correctly in the main thread (form1).

Code: Pascal  [Select][+][-]
  1. procedure GetDesktopImage(MyImg: TJpegImage);
  2. var
  3.   ScreenDC   : HDC;
  4. begin
  5.      if Assigned(MyImg) then
  6.      begin
  7.        ScreenDC   := GetDC(0);
  8.        try
  9.           try
  10.              MyImg.PixelFormat := pf32bit;
  11.              MyImg.LoadFromDevice(ScreenDC);
  12.              MyImg.CompressionQuality:=Self.FQuality; //100 = best quality, 25 = pretty awful
  13.           finally
  14.             ReleaseDC(0,ScreenDC);
  15.          end;
  16.        except
  17.              on E: Exception do
  18.              begin
  19.                      writeln(E.Message);
  20.              end;
  21.        end;
  22.      end;
  23. end;
  24.  
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: xinyiman on October 18, 2020, 01:06:22 pm
Example who reproduce error.
Terminal write:

Failed to load module "canberra-gtk-module"
[DEBUG] Name com.canonical.AppMenu.Registrar does not exist on the session bus

Pre error
[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
test: ../../src/xcb_io.c:163: dequeue_pending_request: asserzione "!xcb_xlib_unknown_req_in_deq" non riuscita.
Annullato (core dump creato)
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: xinyiman on October 19, 2020, 07:14:25 am
No idea?!
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: devEric69 on October 19, 2020, 08:57:16 am
Hello,

For information, your project doesn't compile at all, on my computer (Ubuntu): "the project (test.lpr) has no main source file.".
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: xinyiman on October 19, 2020, 09:17:31 am
Probably because I use the trunk version of lazarus and fpc. Just from the project analyzer add the * .lpr file from the file system and LCL as a dependency.
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: devEric69 on October 19, 2020, 09:23:37 am
Done: don't compile either.
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: Handoko on October 19, 2020, 09:36:04 am
Have you tried wp's fixlp? Read more on this post:
https://forum.lazarus.freepascal.org/index.php/topic,51388.msg379377.html#msg379377 (https://forum.lazarus.freepascal.org/index.php/topic,51388.msg379377.html#msg379377)
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: devEric69 on October 19, 2020, 10:10:45 am
No, fixlp doesn't correct the "test" project, on my computer in any case (no time to investigate why now):

Code: Bash  [Select][+][-]
  1. sudo test.lpi
  2. Processing test.lpi...
  3. An unhandled exception occurred at $00000000004CEEBB:
  4. EFOpenError: Unable to open file "test.lpi"
  5.   $00000000004CEEBB line 151 of lazutf8classes.pas
  6.   $00000000004CECB8 line 129 of lazutf8classes.pas
  7.   $0000000000486991 line 4186 of laz2_xmlread.pas
  8.   $0000000000401D9A line 132 of fixlp.lpr
  9.   $0000000000401FC7 line 160 of fixlp.lpr

By the way: my SVN-RabbitVCS reports, that currently fpc is no longer in the svn HEAD (already reported here: https://forum.lazarus.freepascal.org/index.php/topic,51828.msg381191.html#msg381191 (https://forum.lazarus.freepascal.org/index.php/topic,51828.msg381191.html#msg381191)).
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: xinyiman on October 19, 2020, 10:16:59 am
Done: don't compile either.

Add umain.pas from project analyzer
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: bytebites on October 19, 2020, 10:21:45 am
Maybe you should do the screen capture in the main thread.
https://wiki.freepascal.org/Multithreaded_Application_Tutorial
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: devEric69 on October 19, 2020, 10:29:34 am
Quote
Add umain.pas from project analyzer

Done (add test.lpr and umain.pas as files, LCL as package, with the Project inspector): same message.


Okay, I recreated the project. I've got: class 'FPImageException' with message: Failed toget raw image from device on line MyImg.LoadFromDevice(ScreenDC);, too.
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: xinyiman on October 19, 2020, 10:55:22 am
Maybe you should do the screen capture in the main thread.
https://wiki.freepascal.org/Multithreaded_Application_Tutorial

I can't for performance reasons. If I have to switch to the main thread every time it slows down too much. I'd rather avoid. Because actually in the application I want to create I not only have an additional thread, but at least 4 others.
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: xinyiman on October 19, 2020, 10:56:00 am
Has anyone been able to compile and run it in order to reproduce the error?
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: devEric69 on October 19, 2020, 11:00:48 am
I have the same error, and...:
Quote
WARNING: TGtk2WidgetSet.RawImage_FromDrawable: gdk_image_get failed
Failed to get raw image from device.
... from gtk2widgetset.inc, line Image := gdk_image_get(ADrawable, ARect.Left, ARect.Top, ADesc.Width, ADesc.Height); , which raises the exception class 'FPImageException' with message: Failed toget raw image from device on line MyImg.LoadFromDevice(ScreenDC);.

==> So, it's not due to a specific problem with the GTK layer of your computer.
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: winni on October 19, 2020, 11:20:08 am
Maybe you should do the screen capture in the main thread.
https://wiki.freepascal.org/Multithreaded_Application_Tutorial

I can't for performance reasons. If I have to switch to the main thread every time it slows down too much. I'd rather avoid. Because actually in the application I want to create I not only have an additional thread, but at least 4 others.

Hi!

So this is error by design.
Read the link from bytebites again.

Winni
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: ttomas on October 19, 2020, 11:55:47 am
GUI request are not thread safe.
For win https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: jamie on October 19, 2020, 01:27:15 pm
yeah , yes or no but since this is Linux and the gtk interface it may not be the same..

however, if you use a synchronize method call from a thread I would be it to work, but them again it was stated about slow down. hmm. something tells me someone is trying to run a real time screen capture... naughty !
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: xinyiman on October 19, 2020, 01:54:26 pm
something tells me someone is trying to run a real time screen capture... naughty !
Exactly
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: devEric69 on October 19, 2020, 02:20:21 pm
For information, taking a screenshot works very well under Linux (Ubuntu distro.) + GTK2, from a TForm.  Cf. the project Lazarus/...\.../examples/canvas_test/canvastest.lpi, with this code:
Code: Pascal  [Select][+][-]
  1. procedure TfrmScreenshot.btnScreenshotClick(Sender: TObject);
  2. var
  3.   bmp: TBitmap;
  4.   DC: HDC;
  5. begin
  6.   bmp := TBitmap.Create;
  7.   DC := GetDC(0);
  8.   try
  9.     bmp.LoadFromDevice(DC);
  10.   finally
  11.     ReleaseDC(0, DC);
  12.   end;
  13.   imgScreenshot.Picture.Bitmap.Assign(bmp);
  14.   FreeAndNil(bmp);
  15. end;  
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: trev on October 19, 2020, 02:24:26 pm
Cross-platform to boot :)

See also taking a screenshot and excluding your application (https://wiki.freepascal.org/Developing_with_Graphics#Taking_a_screenshot_of_the_screen).
Title: Re: Ubuntu problem with Jpg LoadFromDevice into multithreading
Post by: winni on October 19, 2020, 06:08:43 pm
Hi!

I was interested  about the speed of an endless loop taking a screenshot and assign it to an image.

That's what I did:
Code: Pascal  [Select][+][-]
  1. var loopRunning : Boolean = false;
  2.  
  3. procedure TForm1.Test1Click(Sender: TObject);
  4.    var
  5.       bmp: TBitmap;
  6.       DC: HDC;
  7.       Starttime: QWord;
  8.     begin
  9.       LoopRunning := NOT LoopRunning;
  10.       if loopRunning then
  11.       begin
  12.       repeat
  13.         Starttime := GetTickCount64;
  14.         bmp := TBitmap.Create;
  15.         DC := GetDC(0);
  16.       try
  17.         bmp.LoadFromDevice(DC);
  18.         application.ProcessMessages;
  19.       finally
  20.         ReleaseDC(0, DC);
  21.       end;
  22.       bmp.Canvas.TextOut(10,10,IntToStr(GetTickCount64-Starttime)+' ms');
  23.       image1.Picture.Bitmap.Assign(bmp);
  24.       FreeAndNil(bmp);
  25.       application.ProcessMessages;
  26.       until NOT loopRunning;
  27.    end;
  28.   end;
  29.  

Important is the application.ProcessMessages in the loop so that you can access the machine.

Without any other user actions the needed time per loop is 13-15 ms on my hardware.
Top says it needs 67% CPU time out of 800%.

I Think much higher speed you will not reach with Lazarus.
Except better hardware.
Or except creating low level routines.

Winni
TinyPortal © 2005-2018