Jump to content


Popular Content

Showing content with the highest reputation on 05/23/20 in all areas

  1. So, I found some interesting details, which all seem to point to a buggy implementation of TSocket.Accept when targeting Linux. Instead of LConnectionSocket := FServerSocket.Accept(500); if Assigned(LConnectionSocket) then begin ... I wrote the following code: LReadFds := TFDSet.Create(Self); LWaitResult := FServerSocket.Select(ReadFds, nil, nil, 500); if LWaitResult := TWaitResult.wrSignaled then begin LConnectionSocket := FServerSocket.Accept; if Assigned(LConnectionSocket) then begin Log('Daemon - New connection - ' + LConnectionSocket.RemoteAddress + ':' + IntToStr(LConnectionSocket.RemotePort)); LConnectionThread := TTCpConnectionThread.Create(LConnectionSocket); ... ... and it works, both when compiled for Windows and Linux ! The difference being that TSocket.Accept is now called without a parameter (infinite wait, but returns immediately because a client connection is pending), this pointed to the problematic implementation of TSocket.Accept with a timeout: if not (TSocketState.Listening in FState) then raise ESocketError.CreateRes(@sSocketNotListening); Result := nil; if Timeout <> INFINITE then begin FD_ZERO(FDR); _FD_SET(FSocket, FDR); time.tv_sec := Timeout div 1000; time.tv_usec := (Timeout mod 1000) * 1000; Res := socketselect(1, @FDR, nil, nil, @time); // << this is where things go wrong when compiled for Linux CheckSocketResult(Res, 'select'); if Res = 0 then Exit; end; Len := SizeOf(Addr); ClientHandle := acceptsocket(FSocket, Addr, Len); CheckSocketResult(ClientHandle, 'accept'); Result := GetClientSocket(ClientHandle, Addr); The problem is the call to socketselect(1, @FDR, nil, nil, @time). This code works fine in Windows because the first hardcoded parameter (nfds = 1) is ignored. However, in Linux, this parameter must be the set to the highest-numbered file descriptor in any of the three sets + 1. So for Linux, this implementation is telling socketselect() to only look at file descriptor 0, which is almost certainly not what the socket is set to. This is however correctly implemented in TSocket.Select (I am not sure why TSocket.Accept does not simply call TSocket.Select, rather than re-implementing the same functionality at low level): ReadFds := GetFds(CheckRead); WriteFds := GetFds(CheckWrite); ErrorFds := GetFds(CheckError); if Microseconds >= 0 then begin time.tv_sec := Microseconds div 1000000; time.tv_usec := Microseconds mod 1000000; TimePtr := @time; end else TimePtr := nil; Res := socketselect(Max(GetMaxFds(CheckRead), Max(GetMaxFds(CheckWrite), GetMaxFds(CheckError))) + 1, ReadFds, WriteFds, ErrorFds, PTimeVal(TimePtr)); CheckSocketResult(Res, 'select'); if Res = 0 then Result := TWaitResult.wrTimeout else Result := TWaitResult.wrSignaled; More information about the low level call to select() can be found here: https://stackoverflow.com/questions/2008059/socket-select-works-in-windows-and-times-out-in-linux I guess the next step is to report this as a bug to Embarcadero...
  2. Fr0sT.Brutal

    app logins

    Honestly didn't read thoroughly - too much text. If you've got to store some user-related data then you have to use accounts. Or you may save things in local storage but it has drawbacks
  3. I would not draw directly on the canvas. Use TShapes. You may also want to have a look at this selection component that is part of FMX: TSelection
  4. Yóu can draw like this. But the Canvas is a raster-based area, which doesn't contain graphical objects. So the only way would be to re-paint the objects, as you like. Usually this is done via FrameBuffer bitmaps, where you can do the clearing and drawing, and then paint the whole frame buffer to the canvas each frame (or when changed).
  5. May be if you used different approach, like send aAction to fFrames, let each frame decide if it does need refresh or not, in other word decentralize those actions, like using plugins, if it is a refresh then send a refresh to all.
  6. I present a simple technique that uses a combination of generics and static class variables to map any Delphi type to a simple integer index. And why you would want to... https://blog.grijjy.com/2020/04/21/mapping-delphi-types-to-indices-at-compile-time/
  7. Hi, Some might already know Delphinus. But for those who don't i thought i make a little introduction post, to have a thread for discussion, as I never made one for the international Delphi-Praxis. Questions are always welcome. Delphinus is an opensource Packagemanager for Delphi, which I started in 2015. It has support for Delphi XE and newer. In addition to an IDE integration for package-management, Delphinus comes with a commandline, too. This has the benefit of having a single interface for managing multiple IDEs or run setup-scripts automatically. Currently, packages are provided through Github by preparing a repo to appear in a special Github-Query Delphinus uses to detect packages (See wiki link below). For optimal use, you should add a OAuth-Token to the Delphinus-Config(See wiki link below). Otherwhise you'll hit rate-limits. Offline installation from a folder is provided through the IDE-UI(Folder Symbol). Adding support for creating local folder based repositories for mirroing is planned. Delphinus packages have support for: Copying (source) files Compiling and (if Designtime) installing BPLs Compiling and installing IDE-Experts setting up Search/Browsing path Dependencies to other Delphinus-Packages Optionally, BPLs and Experts may be included as precompiled binary, if your project is closed source. Packages are installed per IDE. I'm working on per project installations. GithubRepository of Delphinus: https://github.com/Memnarch/Delphinus Wiki: https://github.com/Memnarch/Delphinus/wiki My Blog were I (in addition to ther Delphiprojects) post updates about Delphinus: http://memnarch.bplaced.net/ Websetup: http://memnarch.bplaced.net/blog/delphinus/