You are not logged in.
using TSQLRestServerDB, when a error batchupdate cause by "EngineBatchSend: Wrong PUT",
then subsequent batchupdate will generate Server Error 500: Internal Server Error.
Debug find av occur at
function TSQLRestServerDB.InternalExecute(const aSQL: RawUTF8;
if (ValueInt=nil) and (ValueUTF8=nil) then begin
// default execution: loop through all rows
repeat until fStatement^.Step<>SQLITE_ROW; //<====== av occure at here,
//raised exception class EAccessViolation with message 'Access violation at address 006BE19C
thanks!
Offline
I can't reproduce such a problem here.
The context is unclear...
Is there a "Wrong PUT" error before, or after the AV?
GetAndPrepareStatement() should have set the fStatement instance.
Could you step in the debugger and find out why there is something wrong with fStatement?
Offline
I meet the BatchSend returns HTTP 500 or 501 by chance of using BatchAdd with ForceID wrongly.
Something like this:
aPeople: TSQLPeople;
Client: TSQLRestClientURI;
ResultsArray: TIDDynArray;
.....
aPeople.IDValue := 1000;
Client.BatchStart(nil, 1000);
Client.BatchAdd(aPeople, True, True);
Client.BatchAdd(aPeople, True, True); // reproduce the duplicated key in the table People.
Client.BatchSend(ResultsArray);
After this BatchSend fails, all the subsequent BatchStart..BatchSend will fail as well. And the server goes malfunction and consumes nearly all the CPU resource available.
Offline
The context is unclear...
Is there a "Wrong PUT" error before, or after the AV?
"Wrong PUT" error is first, this is the call stack
:76c85608 KERNELBASE.RaiseException + 0x48
mORMot.TSQLRestServer.EngineBatchSend(nil,'["automaticTransactionPerRow",2147483647,,"PUT@VoyageFee",{"ID":null,"Flag":1,"UpdateBy":"User","UpdateTime":1499911738644,"RemoteIP":"127.0.0.1"},"PUT@VoyageFee",{"ID":3096,"Flag":1,"UpdateBy":"User","UpdateTime":1499911738644,"RemoteIP":"127.0.0.1"},"PUT@VoyageFee",{"ID":3086,"Flag":1,"UpdateBy":"User","UpdateTime":1499911738644,"RemoteIP":"127.0.0.1"},"PUT@VoyageFee",{"ID":3084,"Flag":0,"DoneBill":1,"UpdateBy":"User","UpdateTime":1499911738644,"RemoteIP":"127.0.0.1"},"PUT@VoyageFee",{"ID":3086,"Flag":0,"DoneBill":1,"UpdateBy":"User","UpdateTime":1499911738644,"RemoteIP":"127.0.0.1"},"PUT@VoyageFee",{"ID":3096,"Flag":0,"DoneBill":1,"UpdateBy":"User","UpdateTime":1499911738644,"RemoteIP":"127.0.0.1"},"PUT@VoyageFee",{"ID":null,"Flag":0,"DoneBill":1,"UpdateBy":"User","UpdateTime":1499911738644,"RemoteIP":"127.0.0.1...
mORMot.TSQLRestServer.Batch($221C680)
uShipAgentRestServer.TShipAgentRestServer.ApplyUpdates($221C680)
mORMot.TSQLRestServerURIContext.ExecuteSOAByMethod
mORMot.TSQLRestServerURIContext.ExecuteCommand
mORMot.TSQLRestServer.URI($54CFD80)
mORMotHttpServer.TSQLHttpServer.Request($22B78D8)
SynCrtSock.THttpServerGeneric.Request($22B78D8)
SynCrtSock.THttpServer.Process($22152E0,4,$22CC2F8)
SynCrtSock.THttpServerResp.Execute
:004574b9 ThreadProc + $45
:00407e4a ThreadWrapper + $2A
:76e97c04 KERNEL32.BaseThreadInitThunk + 0x24
:7718ad2f ntdll.RtlInitializeExceptionChain + 0x8f
:7718acfa ntdll.RtlInitializeExceptionChain + 0x5a
after wrong Put, BatchUpdate will error, there have two debug Exception Notification:
when click Break, the first callstack is
:76c85608 KERNELBASE.RaiseException + 0x48
SynSQLite3Static.sqlite3_realloc($2212F78,145)
the second callstack is
:76c85608 KERNELBASE.RaiseException + 0x48
:00407224 NotifyNonDelphiException + $1C
:7716ff13 ;
SynCommons.MoveX87
:7717068f ntdll.KiUserExceptionDispatcher + 0xf
SynLog.TSynMapFile.Log($22CC7D8,6696455,False)
SynLog.TSynLog.AddStackTrace(nil)
SynLog.TSynLog.LogInternal(sllError,'% for % // %',(...),$288E960)
SynLog.TSynLog.Log(sllError,'% for % // %',(...),$288E960)
mORMot.TSQLRest.InternalLog('% for % // %',(...),sllError)
mORMotSQLite3.TSQLRestServerDB.GetAndPrepareStatementRelease($22AD0F8,'')
mORMotSQLite3.TSQLRestServerDB.InternalExecute('UPDATE InvoiceType SET Attribute=:(''5''):,UpdateBy=:(''User''):,UpdateTime=:(1499911820772):,RemoteIP=:(''127.0.0.1''): WHERE RowID=:(4):;',False,nil,nil {''},nil,nil,nil)
mORMotSQLite3.TSQLRestServerDB.EngineExecute('UPDATE InvoiceType SET Attribute=:(''5''):,UpdateBy=:(''User''):,UpdateTime=:(1499911820772):,RemoteIP=:(''127.0.0.1''): WHERE RowID=:(4):;')
mORMot.TSQLRest.ExecuteFmt('UPDATE % SET % WHERE RowID=:(%):;',(...))
mORMotSQLite3.TSQLRestServerDB.MainEngineUpdate(23,4,'{"Attribute":"5","UpdateBy":"User","UpdateTime":1499911820772,"RemoteIP":"127.0.0.1"}')
mORMot.TSQLRestServer.EngineUpdate(23,4,'{"Attribute":"5","UpdateBy":"User","UpdateTime":1499911820772,"RemoteIP":"127.0.0.1"}')
mORMot.TSQLRestServer.EngineBatchSend(nil,'["automaticTransactionPerRow",2147483647,"PUT@InvoiceType'#0#0'{"ID":4{"Attribute":"5","UpdateBy":"User","UpdateTime":1499911820772,"RemoteIP":"127.0.0.1"}]',(304),0)
mORMot.TSQLRestServer.Batch($221C680)
uShipAgentRestServer.TShipAgentRestServer.ApplyUpdates($221C680)
mORMot.TSQLRestServerURIContext.ExecuteSOAByMethod
mORMot.TSQLRestServerURIContext.ExecuteCommand
mORMot.TSQLRestServer.URI($54CFD80)
mORMotHttpServer.TSQLHttpServer.Request($22B78D8)
SynCrtSock.THttpServerGeneric.Request($22B78D8)
SynCrtSock.THttpServer.Process($22152E0,5,$22CC2F8)
SynCrtSock.THttpServerResp.Execute
:004574b9 ThreadProc + $45
:00407e4a ThreadWrapper + $2A
:76e97c04 KERNEL32.BaseThreadInitThunk + 0x24
:7718ad2f ntdll.RtlInitializeExceptionChain + 0x8f
:7718acfa ntdll.RtlInitializeExceptionChain + 0x5a
I use this code make test:
TShipAgentRestServer= class(TSQLRestServerDB)
private
f: boolean;
publshied
procedure ApplyUpdates(Ctx: TSQLRestServerURIContext);
procedure TShipAgentRestServer.ApplyUpdates(Ctx: TSQLRestServerURIContext);
var
tempStr: rawUTF8;
begin
if not f then begin
Tempstr := AnyTextFileToRawUTF8('error.json');
Ctx.Call.InBody := TempStr;
f := True;
end else begin
Tempstr := AnyTextFileToRawUTF8('good.json');
Ctx.Call.InBody := TempStr;
end;
Batch(Ctx);
end;
error.json
["automaticTransactionPerRow", 2147483647, "PUT@VoyageFee", {
"ID": 3084,
"Flag": 1,
"UpdateTime": 1499822856618,
"RemoteIP": "127.0.0.1"
}, "PUT@VoyageFee", {
"ID": 3096,
"Flag": 0,
"UpdateTime": 1499822856618,
"RemoteIP": "127.0.0.1"
}, "PUT@VoyageFee", {
"ID": null,
"Flag": 1,
"UpdateTime": 1499822856618,
"RemoteIP": "127.0.0.1"
}, "PUT@VoyageFee", {
"ID": 3098,
"Flag": 1,
"UpdateTime": 1499822856618,
"RemoteIP": "127.0.0.1"
}]
good.json
["automaticTransactionPerRow", 2147483647, "PUT@VoyageFee", {
"ID": 3084,
"Flag": 1,
"UpdateTime": 1499822856618,
"RemoteIP": "127.0.0.1"
}, "PUT@VoyageFee", {
"ID": 3096,
"Flag": 0,
"UpdateTime": 1499822856618,
"RemoteIP": "127.0.0.1"
}, "PUT@VoyageFee", {
"ID": 3098,
"Flag": 1,
"UpdateTime": 1499822856618,
"RemoteIP": "127.0.0.1"
}]
make a web client, call ApplyUpdates with any success content,
first call trigger error, then subsequent call will error,
Use DelphiXE, mORMot 3705, thanks!
Offline
Further debug, after first "Wrong PUT" error, subsequent BatchUpdate generate av at
function TSQLRequest.Step: integer;
{$ifdef RESETFPUEXCEPTION} // safest to reset x87 exceptions - inlined TSynFPUException
var cw87: word;
{$endif}
begin
if Request=0 then
raise ESQLite3Exception.Create(RequestDB,SQLITE_MISUSE,'Step');
{$ifdef RESETFPUEXCEPTION}
cw87 := Get8087CW;
try
{$endif}
result := sqlite3_check(RequestDB,sqlite3.step(Request),'Step'); //<==== here generate av
{$ifdef RESETFPUEXCEPTION}
finally
Set8087CW(cw87);
end;
{$endif}
end;
can't debug further because my ability, seem all av relative to the first "Wrong PUT" error.
When debug first "Wrong Put" error, follow step also generate some av, and when you close
applicaiton directly, final will have Runtime error 216.
thanks!
Offline
Please check https://synopse.info/fossil/info/1d39554271
This was a nasty bug, for sure...
Sorry!
Offline
After test, I confirm AV gone, server is still online.
Wonderful, you are a super man!
thanks!
Offline
Such buffer overflows can be tricky to fix.
I found the issue by reproducing the problem in the batch, with FastMM4 in FullDebugMode.
This mode allows to trigger the Access violation as soon as possible, i.e. in the UniqueRawUTF8ZeroToTilde() function, sooner than in TSQLRequest.Step
Offline
Such buffer overflows can be tricky to fix.
something need to learn, thank your share!
Offline