ertank 27 Posted January 20, 2021 Hello, I have following code running in a thread when application starts. procedure TMainForm.SetSystemTime(); var Sntp: TIdSNTP; begin Sntp := TIdSNTP.Create(nil); try Sntp.Host := 'pool.ntp.org'; try Sntp.SyncTime(); except // eat exception, we are in thread end; finally Sntp.Free(); end; end; When there is no internet connection, thread above code runs is never terminated. I could not find some connection timeout setting for IdSNTP. Is there any other way to terminate Sntp.SyncTime() if it is not completed for a certain period of time like 10 seconds. There is a location with a corporate firewall (with some weird settings I believe) where check for an internet connection is true, but above code still hangs. Thanks & Regards, Ertan Share this post Link to post
Lars Fosdal 1792 Posted January 20, 2021 TIdSNTP.ReceiveTimeout defaults to IdTimeoutInfinite; (-2). Try setting it to the desired timeout interval in milliseconds? Share this post Link to post
ertank 27 Posted January 20, 2021 I forgot to mention in my initial post that I have already tried to change ReceiveTimeout to 2000 with no success. Sorry about that. Since ReceiveTimeout did not work that makes me believe there is a kind of a problem like privilege or initial connection. I do not know though. I cannot access to computers in that location for better understanding. Share this post Link to post
ertank 27 Posted January 20, 2021 I just read it. Thanks for sharing. It seems similar. But, in this thread, code continues and not hangs like in my case. If I had same problem, thread would terminate without clock being synced. My problem is thread not terminating. One additional information I should share is that procedure is threaded using ITask like below. uses System.Threading, uUtils.Log; procedure TForm2.FormCreate(Sender: TObject); var Task: ITask; begin Log('Creating thread'); Task := TTask.Create(SetSystemTime); Task.Start(); Log('Thread started'); end; procedure TForm2.IdSNTP1Connected(Sender: TObject); begin Log('SNTP Connected'); end; procedure TForm2.IdSNTP1Disconnected(Sender: TObject); begin Log('SNTP Disconnected'); end; procedure TForm2.IdSNTP1Status(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string); begin Log('SNTP status: ' + AStatusText); end; procedure TForm2.SetSystemTime(); var Sntp: TIdSNTP; begin Log('SetSystemTime(): System clock sync starting'); Sntp := TIdSNTP.Create(nil); try Sntp.OnConnected := IdSNTP1Connected; Sntp.OnDisconnected := IdSNTP1Disconnected; Sntp.OnStatus := IdSNTP1Status; Sntp.Host := 'pool.ntp.org'; Sntp.ReceiveTimeout := 2000; try Log('SetSystemTime(): Running actual time sync...'); Sntp.SyncTime(); Log('SetSystemTime(): System clock sync completed'); except on E: Exception do begin Log('SetSystemTime(): ' + E.Message); end; end; finally Sntp.Free(); end; Log('SetSystemTime(): Done'); end; That code sample is from a project that I am preparing with detailed logging to help identifying the problem. That code running on my system produces with following lines: 2021-01-20 14:56:58.949 Creating thread 2021-01-20 14:56:58.952 Thread started 2021-01-20 14:56:58.953 SetSystemTime(): System clock sync starting 2021-01-20 14:56:58.953 SetSystemTime(): Running actual time sync... 2021-01-20 14:56:59.067 SetSystemTime(): System clock sync completed 2021-01-20 14:56:59.068 SetSystemTime(): Done As you can see, there is no connection or disconnection here. Problem might be privilege but, this should not hang whole thread and should just exit from it. BTW, I just learned (by chance talking to a colleague) that problem occurs only on Windows 10 OSes and not on Windows 7 or Windows XP. Share this post Link to post
Lars Fosdal 1792 Posted January 20, 2021 So - on the problem system - the log stops before "sync completed" ? Is the process running elevated? Is there anything in the windows logs? What about the local firewall settings on the problem PC - does it allow UDP through? Share this post Link to post
Fr0sT.Brutal 900 Posted January 20, 2021 I was forced to throw out my own timesync service on Windows when servers my apps are running on were joined to domain. Even with allowing domain policy I couldn't get time changing working. So first check if your app is able to change time at all (just call SetSystemTime without any network requests). Share this post Link to post
Remy Lebeau 1394 Posted January 20, 2021 4 hours ago, ertank said: My problem is thread not terminating. But WHERE is it hanging exactly? You need to determine that. Is it on the actual transmission of the request packet? On the receiving of the response packet? On the setting of the PC clock? Your code is calling only 1 method (SyncTime), but that method does multiple things internally, so there are multiple points of failure. Have you tried to use a packet sniffer, like Wireshark, to make sure the SNTP request is actually being sent, and an SNTP response is being received? 4 hours ago, ertank said: As you can see, there is no connection or disconnection here. That is because SNTP runs over UDP, so there is no connection, like you are thinking of. A UDP socket can be "connected" to a remote peer by assigning the peer's IP address statically to the UDP socket, thus sends/receives via that socket will interact only with that particular IP. But that is optional. Your code is not calling the TIdSNTP.Connect() method to establish such a static association, which is why you are not seeing the OnConnected/OnDisconnected events being fired. By default, TIdSNTP will simply write a datagram to the network and then wait for a responding datagram to come back from any peer to TIdSNTP's sending port, which is usually fine in most cases. Share this post Link to post
ertank 27 Posted January 21, 2021 (edited) Thank you to all. My request to have access to problematic computer will not be possible until March 15 due to Covid-19 close down. I will be able to do further analysis after I do have access. Edited January 21, 2021 by ertank Share this post Link to post
Ian Branch 127 Posted January 21, 2021 (edited) You might also want to test the success of SyncTime.. ... .... if Sntp.SyncTime() then Log('SetSystemTime(): System clock sync completed') else Log('SetSystemTime(): System clock sync failed'); .... .... It fails on my Win 10 PC and on a 2012 Server. It is OK if the App is run as Administrator. I wonder if there is a way to have just the routine run at elevated level??? Ian Edited January 21, 2021 by Ian Branch Share this post Link to post
Remy Lebeau 1394 Posted January 21, 2021 12 hours ago, Ian Branch said: I wonder if there is a way to have just the routine run at elevated level??? That would require moving the routine into a separate process or COM object that can then run elevated. Share this post Link to post
Ian Branch 127 Posted January 21, 2021 Hi Remy, Ahh. Thank you. At least I know it is possible. :-) Pardon my ignorance but which would be the easiest to achieve? Without giving me the answer, can you point me where to look? Regards, Ian Share this post Link to post
Remy Lebeau 1394 Posted January 22, 2021 3 hours ago, Ian Branch said: Pardon my ignorance but which would be the easiest to achieve? Starting a new elevated process can be done using the Win32 API ShellExecute/Ex() with the "runas" verb. Instantiating an elevated COM object can be done using the COM Elevation Moniker. Share this post Link to post
Ian Branch 127 Posted January 22, 2021 Hi Remy, Ahhh. I see it now. Didn't think at all of a separate App. Regards & Tks. Ian Share this post Link to post