Kas Ob.
Members-
Content Count
464 -
Joined
-
Last visited
-
Days Won
8
Everything posted by Kas Ob.
-
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
A lot being said above, and you need to start and fig deeper and learn why and how. Anyway, this issue is also easy to fix, the cause is this declaration in GR32.pas PColor32Array = ^TColor32Array; TColor32Array = array [0..0] of TColor32; // pain in the back, and will trigger overflow check TArrayOfColor32 = array of TColor32; And the fix or another slap work around without testing but again using my extra power procedure TRenderer.ApplyRemovedTerrain(X, Y, W, H: Integer); type TTempHackColor32Arr = array [0.. MaxInt div SizeOf(TColor32) -1 ] of TColor32; PTempHackColor32Arr = ^TTempHackColor32Arr; var //PhysicsArrPtr, TerrLayerArrPtr: PColor32Array; PhysicsArrPtr, TerrLayerArrPtr: PTempHackColor32Arr; cx, cy: Integer; MapWidth: Integer; // Width of the total PhysicsMap begin // This has two applications: // - Removing all non-solid pixels from rlTerrain (possibly created by blending) // - Removed pixels from PhysicsMap copied to rlTerrain (called when applying a mask from LemGame via RenderInterface) PhysicsArrPtr := PTempHackColor32Arr(PhysicsMap.Bits); TerrLayerArrPtr := PTempHackColor32Arr(fLayers[rlTerrain].Bits); The best is to fix GR32 with the following, but don't do that on your own, this is up to Anders PColor32Array = ^TColor32Array; //TColor32Array = array [0..0] of TColor32; TColor32Array = array [0.. MaxInt div SizeOf(TColor32) -1 ] of TColor32; TArrayOfColor32 = array of TColor32; -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
@Willicious I am sorry ! I just tried tried again to build the code for this one https://github.com/Willicious/SuperLemmixPlayer assuming it is the one we are talking about, the readme for this one pointing that Graphics32 is needed and it is, but Graphics32 is not compatible with XE8 or 10, it does have inline variables and recent version of generics that i don't have a clue when they are supported. I don't know even the of the game is compliable with my IDEs, so i can't help beyond eyeballing the code in the IDE, even these IDEs are failing to navigate and i had to use search and that is it. Will produce performance hit, but like that easy to find and fix memory leak, they will prevent such and many many more bugs, so you don't need to enable them all the time, if the performance hit is huge then you can disable them for production or release, yet i like to keep them enabled and disable them in critical parts, but this and from what i see, is too soon, so keep them enabled and fix every exception raised with them is good for now. Though from your screenshot and the CPU usage i don't think these checks performance hit will be noticeable in this application. -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
Well, you are in for a ride ! These runtime checks might be triggered many times, as the code never or may be for long times evolved without being checked against these. Anyway, each and every case can be fixed, just take your time with them. For this case : 1) GetTickCount is Cardinal (DWORD), thing to remember. 2) That loop is easy to understand and rewrite performing such subtraction or just slap a workaround around it like this while (RemainingTime >= 0) do begin if (RemainingTime <> OldRemainingTime) then begin ScreenImg.Bitmap.MasterAlpha := MulDiv(255, RemainingTime, MAX_TIME); ScreenImg.Update; OldRemainingTime := RemainingTime; end else Sleep(1); if GetTickCount > EndTickCount then // prevent integer overflow Break; RemainingTime := EndTickCount - GetTickCount; <--------------------------------------- this line here end; Application.ProcessMessages; end; You are in for a ride, and definitely worth it. -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
Found this, and this have be understood and remembered when developing for Windows https://learn.microsoft.com/en-us/windows/win32/win7appqual/preventing-hangs-in-windows-applications Off-topic: the last two lines in that article are most fascinating, because C++ exceptions are similar to Delphi exceptions in their dissimilarity to C exceptions, exceptions in callbacks are freaking fatal, and most the time are obscure and untraceable due the failed unwinding (unroll) process. -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
I don't see any strange behavior here, there is no CPU load or any bottle necks, on the contrary the cpu is relaxed and if there is not responding then it is either Sleep or long process that can be moved into a background thread and make it do it fast. I explained my position and opinion about depending or even using Sleep in main thread, and yes i looked at the code and i know what i am talking about. My suggestion is to entertain or research the possibility of removing the dependency on Application Idle handler to either background thread that post messages to the main thread or simple timer doing the same as that Idle Handler, aka emulate it in timer, this should not huge deal at all, on contrary it will make sure of best practice in developing for Windows, remember that ApplicationOnIdle is triggered when no other message seen at this moment, while executing any thing in OnIdle there is no OS message handling, while Windows OS will consider application freeze and no responding after only 5 seconds if the application main thread is did empty/grab message(s) from the message queue, yes 5 seconds. After all these posts in this thread, i may be out of date on what is the top priority bug/problem to fix, is it still non responding menu level selection window or something else, Keep the good work and good luck. -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
TNLCursor leak is easy to find and fix { .. Cursors : array[1..CURSOR_TYPES] of TNLCursor; .. procedure TGameWindow.InitializeCursor; ... begin ... for i := 1 to CURSOR_TYPES do begin Cursors[i].Free; Cursors[i] := TNLCursor.Create(LocalMaxZoom); procedure TGameWindow.FreeCursors; var i: Integer; begin for i := 0 to Length(Cursors)-1 do // will leak also it could cause AV, yet it seems never did Cursors[i].Free; end; } procedure TGameWindow.FreeCursors; var i: Integer; begin for i := Low(Cursors) to High(Cursors) do // right way Cursors[i].Free; end; The unknown need to be known to be fixed, and i don't have a crystal ball. This unknown might be very similar though, enabling Overflow Checking and Range Checking in the project option should prevent bugs and leaks like the above from first run, but i will guess here it never being enabled, and might be huge task to fix all the exception that will raise, none the less enabling them at least when debugging or developing will yield better code quality with less memory leaks. -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
I remembered the worse of them all, clicking show Desktop aka minimize everything, and an application still there, most annoying thing, sadly the Delphi debugger do this without any sense of consideration i would love to see an animation like a hammer and a nail when it refuse to minimize. -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
No imagination here just logic an make sense. OK, but how it is more complicated, on one hand Sleep doesn't have fixed interval ! right ? any other application running on Windows OS can ruin your timing by 16 fold, i saw it 1ms and saw it 15.625ms, these are the most popular. On other hand either that animation is slow and taking long time or very fast, in both cases a timer or background thread will be more appreciated and will not prevent the used from closing the app as as example or not clicking a button, or even worse buffering few clicks form the user then fire them afterward like machine gun. And again if it is one animation then one timer will do it, but if there is more then what more sleep calls, or the same one timer or even more timers, for me this is simple question and simple answer. 300ms delay in IDE autocomplete does feel very different from 200ms, don't you agree ? -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
Also i didn't say this will solve the problem or will work as workaround. Sleep can no be used for timing anywhere, and in this application if it is being used as such then a confirmation is needed. Just like handling Windows control and custom drawing, as example, take Custom Draw events, like ListBox, some might implement to draw one item on every call or even draw the whole list with all the items, still the OS will send punch of draw messages, different messages for might be one or many items, some will simply pointing the X item is not selected followed by Y item selected, while the application just draw the lot twice. -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
I do understand. I want the CPU to spike first, go full core, only after that the reason(s) for the stuttering can be identified or isolated, right now and until now all i got from the description is the CPU is doing nothing yet there is unresponsiveness in UI, after unhinge the CPU and processing loops without break, if the stutter still exist then this will mean a thing if not then it is a different thing and so on. If it is an one-to-one import for very old design like DOS then timing is suffer as modern OS and CPU behave differently and multitasking is shared responsibility between the application and OS, in old days your game should time the rendering and the input and give no concern about OS or other any applications running on the device. When i see a comment in the source right before Sleep(1) call with " // Relax CPU" then many variation comes to mind, relax for whom or to whom as this game is one thread and the OS will switch it when he see fit not waiting for such a sleep, this makes sense if such sleep is inside a never ending loop, is it ? All in all, i can't imagine (what ever) reason to call Sleep from main thread. think about it. -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
Well said and well done but this : This is freaking beautiful, nice. Yesterday only i downloaded https://github.com/ericlangedijk/Lemmix at last and tried to build it, but it is not for older Delphi. This is tricky sometimes, but in your case it is very easy, in that PE tab there is Starting Address, pointing to the module created the thread, in your application there is only one started form your EXE, while when debugging in the IDE yes most likely it is the first one unless an imported DLL invoked one and the debugger captured it, Delphi Debugger leave the threads sorted as they being seen, while Process Explorer sort them by CPU usage by default, and its sort options doesn't have running time. That is not exactly what i said, i said BASS is capable to do all its operations in asynchronous, but only if told to do so, the documentation clear about threading like this not so special case ( from https://www.un4seen.com/doc/#bass/BASS_ChannelSetSync.html ) But now and reading more of BASS documentation i don't think it is the culprit here, because i am sure you did disable all the sound effect if there is any changes then you would already mentioned that. Now to the most important question Well evidently is not, and your application has one thread (main one) and from PE it is doing nothing, yet it is not responding in time, so what ? This project is half doomed to work on modern OS and that is by design, after reading the readme which is clearly is pointing that the structure based on DOS era application, where you must not let the thread go anywhere except looping over handling UI and draw/update the screen. There is huge misconception in this approach with assuming to be working on modern OS, from what caught my eye the application is abusing ApplicationIdle to process almost everything, like this I want to suggest something might be look stupid and might be in fact a stupid thing considering i can build or debug or investigate this deeper, but please try the following: 1) Make sure there is no Sleep calls at all ! everything single one of them , these you have to replace them with timers in needed 2) The core problem is this class and how it does lose control and regain it, when sleeping or out of execution there is no update and when it is activated it is doing small update step just to go into sleep again, (again and again sleep is the problem) 3) put a timer on where application idle or that TIdle is used and make it call the according "Application_Idle(Sender: TObject; var Done: Boolean)" manually instead of depending on the VCL library to do so, this means disabling the handler or work around it, then though it should at least show some CPU processing and greatly raise your FPS in your case the application UI responsiveness. Sender not used so you can fill it with nil, as for Done don't process it for first test, not sure if it should be useful at all, i mean even if an animation is done drawing and we can't(and must not) disable the timer as we emulating OnIdle so calling again is merely a simple check. 4) put these timers intervals at 1 ms, start there to see how animation are being drawn, tweaking this is most likely needed but lets find and understand the structure and logic first. Share your result with us ! ps: i can't say for sure about this TIdle, but there is something wrong about it and about having Application.OnIdle being assigned in few other places other than that TIdle, so there might be some conflict or miss handling, so try to replace the Idle handlers one by one , start with the working ones, just to understand the effect and side effect. -
You missed attaching this image as explanatory material Joking aside : How to use a script to add datetime on checkin like leaving the rversion 0 or whatever to minimize breaking changes, but with an extra string like 202405281850 ? Is that is easy/feasible with SVN ?
-
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
This indicate long process and from the memory graph there is huge allocation(s), but no CPU spike also no spike in IO, this means the process or the main thread was waiting or sleeping, aka doing nothing. While this is concerning, Context Switches at 272k with 3 seconds of User Time, this is too much of thread switching while the code in user mode. See this is my ThunderBird (an old version before switching to Chromium means it is single process) , It was up and running for 6 hours and still doesn't have that much of switching while in CPU cycles used as half of the shown in your screen shot. I asked for 2 different shots to compare with some interval between them, so we can see if these context switches as still happening or stopped after loading the form, and fortunately your screenshot landed on your app main thread, which i didn't explicitly point it to fearing of spending time explaining stuff might not be relevant here, so if you will repost screenshot make sure to select that thread from your EXE. ps: if you will repeat the screenshot then first run Process Explorer as Administrator, i would helpful to see the kernel time. Anyway, and to what i do see: Your application is literally doing nothing, there is no intensive CPU usage at all, but there is two background threads i am concerned about, one from dsound usaualy indicate the directsound is playing or recording, in other words there is an audio operation in work. one from BASS.dll, but not sure about this as i am not familiar with bass, only general and past knowledge, so it might be relevant to the above or might not be. from the above i have a question : Are you playing sound(s) in the background or on mouse movement events ? (are you playing sound effects ?) What ever is the answer, try to stop all audio operation like playing sounds and see how does that impact the responsive of your UI, and please share your finding. One more point : to my knowledge BASS library is fully equipped with background threads handling/playing, so most its operations can be asynchronous, to me your unresponsiveness UI is a symptoms of long synchronous operations called from MainThread, the one that should not be doing much other than handling user input, UI, and essential OS calls/notifications, and of course drawing/updating UI (this drawing is more like slapping already rendered image on a canvas). -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
That depends if you are doing some drawing, updating some visually elements... in other words if the updating the scroller is more than painting already cached images or change position of already ready to draw elements then use a thread to do it, then use the timer to do the paint or the update, but in both cases timer will solve your problem. Main thread is the first thread in your application the one handed the execution form OS starting the dpr code, and called Application.Run, this one is the only one should handle all your UI (VCL/FMX) and their events, MainThread is a name for specific thread and not some generic terminology. Also keep in mind that your MainThread is the one responsible for any stuttering or slow UI handling, so we need to free it from doing anything expensive or might take long time, its job is answering OS messages (aka user and OS input and your specific requests from the OS)as fast as possible, when that is full filled the UI will be smooth, fast and keep up with screen refresh rate. You could share your CPU usage as it might indicate the problem, is it too much work or too much sleep and wait ? To do that, use Process Explorer from Sysinternals, then double click on your application, in that properties window, take screenshot of two tabs, and another screenshot for the following tabs after some time passed like 1 minute or more: Threads Performance Graph These tabs might help identifying strange or wrong behavior or at least will give an insight of the performance in overall. -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
OK, But evidently your application usage of Sleep is showing a problem if understanding its impact, see, Sleep(1) aka sleep for 1 millisecond by default will be 1000/64=15.625 ms, limiting that specific path of code to 64 time per second, this will affect UI greatly, so : 1) Search for every Sleep call in your project from the main thread and remove them, don't use Sleep in main thread not for 1 or even 0 ms, they makes no sense, for background thread it is understandable and useful, but again if the main thread will wait for background thread to finish rendering an animation to paint it then again UI will behave as you described. 2) In my life i may be have used ApplicationIdle few times that can be counted on hand, mostly were to logout or clean up and close stuff or finish opened procedure to not causing blocking something online, but i have removed tens of these handlers from projects that are not mine, due the abuse and misunderstanding of usage, ApplicationIdle is healthy way to see that your UI is responsive the more is called the better, and never use it for something take long time, if needed then start background thread to do it. 3) Your animation most likely is the cause, this is my guess, a thread is doing something while main thread is waiting on it to paint, that is wrong approach, let the thread render (prepare what ever), on other hand use a timer, simple timer with adequate interval to see if that thread or the animation is ready to be painted then draw/paint it, and exit, don't use interval higher than 60 per second, as this is useless and waste of time, on other hand try to centralize all your animations with one timer and one class that do the draw/paint, you don't need every animated button to use 60 message per second, right ? because this will starve UI from handing message and produce the mentioned behavior. -
How to debug a Not Responding program element
Kas Ob. replied to Willicious's topic in Delphi IDE and APIs
You are calling Sleep(interval) in GameScreenMenu.TGameScreenMenu.ApplicationIdle , this interval either too big or being called too many times behaving like deadlock. the problem is not exactly there, but in some sort of combination with waiting on some event or value from the TGameBaseMenuScreen, as this one is in DoLevelSelect is executing ShowModal . So your ShowModal is implemented in the base class while you ApplicationIdle is in the inherited one, now make sure you are not checking on any Form.Handle as it might be recreated in other words, your ShowModal form might be not visible or lost track of some of its internal fields where your Idle handler is waiting on it. Suggestion : 1) redo or completely remove that Idle handler, by redo i mean re-code it in defensive way assuming you can't trust any locally stored values and check them at runtime every time you evaluating something namely and most critically before calling a Sleep, 2) Why on earth you need to call on Sleep to begin with ? if you step back to look at what is going on, OnIdle is executed when the application is Idle and no work to, but you are introducing a work for it by calling Sleep !! -
Delphi Clipboard - WM_CLIPBOARDUPDATE (sent, but no changes)
Kas Ob. replied to PawelPepe's topic in VCL
I have no idea why i wrote "doesn't". -
Delphi Clipboard - WM_CLIPBOARDUPDATE (sent, but no changes)
Kas Ob. replied to PawelPepe's topic in VCL
It doesn't help. -
Delphi Clipboard - WM_CLIPBOARDUPDATE (sent, but no changes)
Kas Ob. replied to PawelPepe's topic in VCL
I used ApiMonitor to track this behavior, the result of all clipboard functions called for MMC.exe : One function in particular is the culprit so i tested it and found SetClipboardViewer(0); // invalid handle here This will trigger sending WM_CLIPBOARDUPDATE to all registered handlers, mmc is calling it, i think many of these system administration tools will call it too. Save the clipboard content or part of it and compare for changes on every WM_CLIPBOARDUPDATE. -
Most likely you can, but just for editing files, it is easier to use Notepad++ than Delphi to edit JavaScript and HTML, from https://developer.kaiostech.com/
-
CTRL+C to a console app vs. TerminateProcess(..)
Kas Ob. replied to Der schöne Günther's topic in Windows API
You nicely summarized the good, the bad and the ugly in spawning console processes. My thoughts here: 1) The role of thumb for console application to be terminated at any time, and these signals or ControlEvent are not to reliable to be depends on, yet there is some cases where they are needed to not lose some job or as you named it gracefully terminate. 2) as for application you pointed to wstcp, i don't see any such event handler in the source, (may be i missed something) but you can check for your self https://rust-cli.github.io/book/in-depth/signals.html 3) As for your own processes then i suggest to try different IPC than standard console pipe, like Memory Sharing, it will give you better speed, like you can use background threads to wait on events or simply let the spawned processed write to the named shared memory passed to them in a command line and the mother process will check with intervals and read ... remember there nothing prevent a spawned from allocating shared memory too for lets say specific temporary file or stream of data and put the name in predefined table which also shared but from the owner process and passed to the child... anyway there is many approaches to handle this, and they all will remove the need the dependency on events like CTRL+C 4) if you not sure if the 3rd party process does require graceful termination then don't use TerminateProcess, make sure all your other process handle such event and either refuse to close or terminate too, but again you need to tell them first through some IPC that an event is coming and should be ignored. Again for that "WebSocket to TCP proxy" it is fine to use terminate process. All the concerning points in ExitProcess are for a process calling ExitProcess itself and it is recommending to switch to TerminateProcess for the case where the same process is not sure if it has a thread locking a detaching DLL callback function, so TerminateThread is safer and should be in mind when designing an application. Also notice my suggestion above for using shared memory and wait can be the worst because of if an application is built to wait on some value in memory shared then TerminateProcess will put the waiting process in deadlock, hence you should a thread to poll the value and not wait, or wait on an event, created by the child process hence the Exit/Terminate will signal it. -
Well, creating self signed certificate for code signing is easy as the certificates for key exchange certificates (aka SSL/TLS), it is in the Extended Key Usage defined by OID against BUT , both above are end certificates and not self signed, and code signing by self signed is no-no for any AV or for SmartScreen for many reason 1) the best practice is to have SelfSigned which will be called root that allow to issued and sign CA or end certificate, am talking out of debugging for developers, out of debugging certificates should never be a self signed. 2) Such self signed and any signed certificate signed (issued) by it (CA and end) must have a way to be revoked, this will bring whole different beast to the table, the certificate must have OCSP and/or CRL server that answer for the validity for this certificates, such server must also time stamp with signature its response, CRL and OCSP are fields in certificate with according OID and specific format, CRL response should be signed by the selfsigned while OCSP is really complex response. Sorry for the extended details, but i think it might be useful for some.
-
@Patrick PREMARTIN , that is very kind and nice, my certificate will expire in a month and would offer to sign useful and needed binaries but not for open source that easily can be build by the same IDE will use it, still it is disturbing to see Embarcadero as chain supplier supply signed code not built by them, again this might be useful for hard to build binaries or closed source projects. First half is somehow fine, the second is NOOOOOOOOOOOOO Don't ever add certificates to your OS trusted store at a whim or for one single binary. The most lethal attacks is the ones that violate trust chain, see, any application you are running on your PC with elevated privileges might/can add trusted certificate, silently, a lethal stage for next part of the attack form different binary that you might download and click, and this time nothing will detect it or stop it. As for Embarcadero then the proposed of self signed or lets say self issued certificate might work, but it should not be in the OS store, it should be in the IDE and only the IDE -well in this case GetIt- will validate that certificate and execute the binary after confirming it is from Embarcadero, that works, it must parse the certificate and run it on its own, then either by notify you it is OK to pass SmartScreen or use a DLL version of the installer and execute it with its privileges, so no OS complains. @dummzeuch Thank you, and no one should ask you to be responsible for securing an an open source project, or waste time and money on that.
-
I just don't get it !?? WHY ? The source is there, and i only can imagine the amount of the hours and work went into it to make it compliable as simple as few clicks, it is not like you need the compiled version for Microsoft Office PowerPoint. Just download the god damn repository (the source) and build it. For the binary from GetIt (not sure if it is there) then it is Embarcadero responsibility to build it and sign it, aka making it trustable. And that it is. Having the source and build it will make it better by ensuring bugs and mistakes are fixed in time and a call to every user to engage in the project.
-
What do you think of "Local Global variables"
Kas Ob. replied to Tommi Prami's topic in RTL and Delphi Object Pascal
Also i am failing now to write one good example to show that behavior with XE8.