DBFL / SQL FB Bug Report

Briefly about the stacks on which this problem manifested itself:

  1. IDE – PLCNext Enginer 2024.0.4 LTS
    Controller – AXCF2152
    Hardware Version - HW: 04 FW: 2024.0.5 LTS
    DBFL Version - 8
  2. IDE – PLCNext Enginer 2024.6
    Controller – AXCF2152
    Hardware Version - HW: 04 FW: 2024.0.5 LTS
    DBFL Version - 8
  3. IDE – PLCNext Enginer 2025.0
    Controller – AXCF2152
    Hardware Version - HW: 06 FW: 2025.6.0 LTS
    DBFL Version – 10
    The program cycle for working with SQL is 4ms

In the end, I chose DBFL Version 10 for testing, as it provides access to the udtDiag structure.
In the process of integration and behavior diagnostics, an error was identified in the logic of processing asynchronous sending, leading to the inability to send data in the presence of short pulses of the REQ input signal.
1. Problem search description
The internal logic of the library is as follows:

  1. A database connection is established via TLS_SOCKET_2.
  2. Waiting for a request from the user
  3. Sending data via TLS_SEND_2
  4. Receiving a response via TLS_RECEIVE_2
    According to Logic Analyzer, I can see that when a problem occurs, the library is always in the state of receiving a response from the database. I created a local database on my work laptop and decided to track the movement of packets and came to the conclusion that the library was not sending the request.

image001.png

The image shows that it went into standby mode after it was sent (the label on the pointer).
Meanwhile, in Wireshark, I see the following

image003.png

The first 3 lines refer to the previous query (example of a successful query):

image005.png

The image shows that the SQL request has arrived

image007.png

The image shows that the response to the request has been sent

image009.png

The image shows that the response to the request has been received

image011.png

As you can see from the packet arrival data, he sent a packet about closing the connection (the closure occurred due to a timeout, the label on the pointer, the sending time approximately corresponds to the arrival time of the packet in Wireshark)

image013.png

From which I concluded that the request does not even arrive at the database server.
2. Checking the reasons for this behavior
Since the library uses TLS_2 function blocks, it was decided to look at working with them.
After examining the internal structure of the PLCnext Controller.pcwlx library files (since version 2025.0, the TLS
_2 block implementation has been moved here), I found that the implementation of these blocks is in the file Arp.Iec.Sockets.dll .
Using the dnSpy tool, I decompiled this file. After studying the library and the program’s capabilities, I came to the conclusion that I can add logs, after looking at which I can understand the reason for this behavior.
Implementation of the TLS_SEND_2 class

     public void __Process()
      {
         ...
         else if (TlsSocketBase.IsFallingEdge(this.REQ, ref this.m_REQ))
         {
             object syncLock = this.m_syncLock;
             lock (syncLock)
             {
                 Log.Warning("Set m_busy in {0}", new object[]{ false});
                 this.m_done = false;
                 this.m_busy = false;
                 this.m_asyncBusy = false;
                 this.m_statusCode = StatusCodes.NoError;
                 this.BUSY = false;
                 this.DONE = false;
                 this.ERROR = false;
                 this.STATUS = 0;
             }
         }
         if (this.REQ)
         {
             bool done = false;
             bool flag2 = false;
             bool flag3 = false;
             this.UpdateFlags(out done, out flag2, out flag3);
             if (flag2 && !flag3)
             {
                 this.SetFlags(done, flag2, true, this.m_statusCode);
                 Log.Warning("WAIT FOR SEND {0}", new object[] {this.HANDLE});
                 ThreadPool.QueueUserWorkItem(new WaitCallback(this.ProcessSend));
             }
         }
      }
      Here I have activated 2 events: unchecking the m_busy flag and queuing for write execution.
     private void ProcessSend(object state)
     {
         Log.Warning("SENDER {0} - working 0", new object[]{this.HANDLE});
         bool flag = false;
         object syncLock = this.m_syncLock;
         lock (syncLock)
         {
             Log.Warning("SENDER {0} - this.m_busy = {1} this.m_asyncBusy = {2}", new object[]{ this.HANDLE, this.m_busy, this.m_asyncBusy});
             if (!this.m_busy && !this.m_asyncBusy)
             {
                 return;
             }
         }
         Log.Warning("SENDER {0} - working 1", new object[]{this.HANDLE});
         StatusCodes statusCode;
         int num = TlsSocketBase.ProcessSend(this.HANDLE, this.SEND_SECURE, out statusCode, out this.m_hasPassiveClose);
         Log.Warning("SENDER {0} - working 2 {1}", new object[]{this.HANDLE, num});
         ...
     }

Here I’ve analyzed some of the steps to understand exactly where it ends. After reviewing the logs, I found the following 08.12.25 06:52:06.634 Arp.Iec.DotNet WARN - WAIT FOR SEND 1073742108 08.12.25 06:52:06.636 Arp.Iec.DotNet WARN - SENDER 1073742108 - working 0 08.12.25 06:52:06.636 Arp.Iec.DotNet WARN - SENDER 1073742108 - this.m_busy = True this.m_asyncBusy = True 08.12.25 06:52:06.637 Arp.Iec.DotNet WARN - SENDER 1073742108 - working 1 08.12.25 06:52:06.638 Arp.Iec.DotNet WARN - Set m_busy in False 08.12.25 06:52:06.644 Arp.Iec.DotNet WARN - SENDER 1073742108 - working 2 115 08.12.25 06:52:07.234 Arp.Iec.DotNet WARN - WAIT FOR SEND 107374210808.12.25 06:52:07.238 Arp.Iec.DotNet WARN - Set m_busy in False08.12.25 06:52:07.240 Arp.Iec.DotNet WARN - SENDER 1073742108 - working 0****08.12.25 06:52:07.241 Arp.Iec.DotNet WARN - SENDER 1073742108 - this.m_busy = False this.m_asyncBusy = False

First 6 lines is a reference, as it was executed, which is confirmed via Wireshark and packet tracking.
The last 4 lines , we see the following, sending the request did not go beyond working 0, since the log shows that this.m_busy = False, this.m_asyncBusy = False We also see that after queuing for sending, a log is executed in which that this.m_busy = False.
By referring to the code, you can see that this log is executed when the condition is met
TlsSocketBase.IsFallingEdge(this.REQ, ref this.m_REQ)
From this, I conclude that the implementation of the DBFL library removes the REQ flag prematurely, and the queued task
ThreadPool.QueueUserWorkItem(new WaitCallback(this.ProcessSend))
Is executed later than the next program cycle is executed.
Since I do not have the opportunity to refer to the DBFL implementation, I was able to draw only this conclusion based on the observations I received.
Please confirm:

  1. The correctness of the identified scenario and the confirmation of the hypothesis about the incorrectness of working with the REQ flag.
  2. Is there a fix planned in a future version of the library?
1 Like

same problem!!!

Hello adryian4ik,

thank you for your inquiry, and please excuse our delayed response.

Our development team has reviewed the issue but was not able to reproduce it.

A new version is scheduled for release in the third quarter, and this update will likely resolve the problem.

If you continue to experience any issues, please contact your sales representatives. They will be able to provide better support for more complex matters.

1 Like

Thank you for the answer!
I can provide a test project on which I received this problem and a description of it.

I assume that for the TLS_SEND_2 block, the REQ flag is prematurely set to FALSE.

What does it mean:

The DBFL_SQL library implementation sets the REQ(TLS_SEND_2) flag to TRUE, and under ideal conditions it will start sending a request (ProcessSend function) BEFORE the next program cycle, so in the next cycle the REQ flag is set to FALSE.

In fact, if the controller is loaded (CPU usage 60-80%), then sending a request (ProcessSend function) will not necessarily start until the next program cycle, and since the REQ(TLS_SEND_2) flag in the next cycle is already in the FALSE state, the packet is not even sent over the network.

Stack:

The IDE version used

The controller used

DBFL_SQL 10(the library used is attached as a separate DBFL_SQL_10.pcwlx file)

The modified PLCnext Controller.pcwlx file is also loaded in the application (the logic of the TLS blocks has NOT changed, only logging has been added to find the problem).

The check was performed in MS SQL Server 2022.

For the tests, you need to create a simple database with 1 table:

CREATE DATABASE TEST;

USE TEST;

CREATE TABLE dbo.Logs (

 *GUID uniqueidentifier DEFAULT NEWID() NOT NULL,*

 *\[DATETIME\] datetime NOT NULL,*

 *STATUS int NOT NULL,*

);

The project contains minimal database work.

The database itself is implemented in SQL_PRG. This program runs in a 4 ms cycle.

The remaining cyclic tasks simulate the load created by other blocks and are necessary to create a more realistic use case.

The G_DATABASE variable specifies the parameters for connecting to the database (you must specify the IP address and authentication data).

The ENABLE variable starts sending requests with a frequency set by TIME_ON/TIME_OFF (by default it is 0.1 seconds for each variable).

To demonstrate the bug, it is enough to set the ENABLE variable to TRUE and run Logic Analyzer.

The Logic Analyzer contains variables that I use to monitor the state: the statuses of sending and receiving data from the database, the status of the TCP connection, as well as the flag by which the DBFL_TSQL_ACCESS block starts executing the request.

The highlighted areas are just talking about the described problem. My assumption is that the request should have been sent, but in fact nothing was sent, the controller is waiting for a response from the database (since nothing came to the database, it does not respond), the timeout goes out, the library closes the connection.

The logs contain the following:

19.12.25 12:39:04.300 Eclr WARN - WAIT FOR SEND 1073741835

19.12.25 12:39:04.303 Eclr WARN - SENDER 1073741835 - working 0

19.12.25 12:39:04.304 Eclr WARN - Set m_busy in False

19.12.25 12:39:04.305 Eclr WARN - SENDER 1073741835 - this.m_busy = False this.m_asyncBusy = False

19.12.25 12:39:04.305 Eclr WARN - LOCK_ACQ RECV: Thread=71 acquired lock on 192.168.4.176:1433

19.12.25 12:39:04.306 Eclr WARN - UNLOCK_ACQ RECV: Thread=71 acquired lock on 192.168.4.176:1433

19.12.25 12:39:04.793 Eclr WARN - LOCK_ACQ RECV: Thread=71 acquired lock on 192.168.4.176:1433

19.12.25 12:39:04.794 Eclr WARN - UNLOCK_ACQ RECV: Thread=71 acquired lock on 192.168.4.176:1433

test.zip (2.0 MB)

1 Like