You are not logged in.
Perfect!
Test are also successfully.
(mget was missing, in build_fpc.sh before compiling test a line for building mget works for me:
>fpc -MDelphi -Sci -Ci -g -gl -gw2 -Xg -k'-rpath=$ORIGIN' -k-L$BIN \
...
-B -Se1 "$LIB2/src/tools/mget/mget.dpr"
But some memleaks were reported:
WARNING! THIS PROGRAM LEAKS MEMORY!
Memory Status:
Small: 33/5KB including tiny<=128B arenas=8 fed from Medium
Medium: 13MB/117MB peak=53MB current=11 alloc=94 free=83 sleep=4
Large: 0B/4GB peak=27MB current=0 alloc=2K free=2K sleep=0
Total Sleep: count=4
Small Blocks since beginning: 54M/5GB (as small=45/46 tiny=56/56)
48=19M 64=10M 16=5M 80=4M 96=2M 528=1M 112=1M 32=1M
Small Blocks current: 33/5KB
128=10 32=8 160=4 304=2 48=2 288=2 112=2 352=2
disable inlining in FastNewString was it! Thanks a lot.
(mormot2tests doesn't compile, I don't know what's wrong. No error, just Error in ./build_fpc.sh on line 117)
Hi Arnaud,
after update (since Februar) I got under linux/fpc 3.2.0 with -02/-03 following av:
An unhandled exception occurred at $000000000052D2F4:
EAccessViolation: Access violation
$000000000052D2F4 CASECOPY, line 7632 of ../../mORMot2/src/core/mormot.core.unicode.pas
$0000000000415F24
$0000000000CA7401 ADDIMPLEMENTATION, line 1803 of ../../mORMot2/src/soa/mormot.soa.server.pas
$000000000051ADAA SERVICEREGISTER, line 7400 of ../../mORMot2/src/rest/mormot.rest.server.pas
With -01 it works. Under Windows/Delphi 10.4 it works too.
Greetings,
Daniel
Thanks for explain, make sense.
So when using plain THttpServer, what's your proposal to set ServerKeepAliveTimeOut:= 0 (disabled keep alive)?
I'm creating just a TRestHttpServer which could creates different kinds of HttpServers (Socket, Api, Async) and ServerKeepAliveTimeOut property isn't public over TRestHttpServer.HttpServer.
--> THttpServer(aTRestHttpServerInstance).ServerKeepAliveTimeOut:= 0; <-- looks like a hack
I'm not using websockets, just plain Http.
But why I shouldn't use async server for that? I use HTTP_DEFAULT_MODE for TRestHttpServer and under linux this leads to useHttpAsync.
And I'm aware (now) of disabled keep alive is not for async server.
What do you mean with plain THttpServer? useHttpSocket?
@dcoun
As I remember I had the same issue with TSynLog for years. It's probably not related to mORMo2 but Windows:
Interesting.
I hadn't issues with wrk and disabled keep-alive, but
under wrk nothing noticed about performance, but
much slower response times in production.
In production enviroment I use ngingx as a reverse proxy. Perhaps this is the difference.
But wrk and errors sound more like a race condition. Perhaps you could test with heaptrc and gdb for a longer time?
Sure is a great word and what does it mean to you, when I am?
Better I show you what the log file says:
20250211 15375400 ! + uHTTPServer.TSOneHttpServer(020f4f28).Create useHttpAsync (secNone) on port 8281
20250211 15375400 ! + mormot.net.async.THttpAsyncConnections(03205f68).Create(THttpAsyncServerConnection,root,32)
20250211 15375401 " info SetThreadName 7f69b8b6c640 140092047279680=R0:root
20250211 15375401 " trace uRestServerDB.TSOneRestServerDB(01dfe208) BeginCurrentThread(TAsyncConnectionsThread) root=root ThreadID=7f69b8b6c640 'R0:root' ThreadCount=1
Hello Arnaud,
a setting of ServerKeepAliveTimeOut:= 0 for TRestHttpServer (async) was the reason for 10x slower req times.
I used this option in past (never change a running system) and I reactivated it yesterday without any knowledge about it.
In context of the super fast progress/changing of mORMot may a ask if this option still usefull/relevant yet?
Hello Arnaud,
I could find the location of our culprit today.
But I'm not able to understand it by now and have to test more.
Thanks
Daniel
@ab
Today we had "same" behavior like @itSDS (I'm looking for errors on our side first and since weeks), but it's not a client issue on our side.
1. service isn't responsive any more (/timestamp over curl gives timeout too).
2. absolut no cpu-usage in any thread
3. no exceptions or error in (verbose) log file before.
4. absolut no timeout in postgres.
Our service runs since yesterday evening and we had about 40' request per hour till the issue at 2:20 pm.
We are using mORMot commit #fe67be7b8 / heap.inc / linux (fpc 3.2.0).
@zen010101
Thanks.
I've also read about it but I wasn't able to belief or understand why it were done this way. When I set a codepage or save a file in utf8, then I expect utf8 and not utf16.
I don't want to waste your time. It's a fpc issue I don't understand.
locale:
LANG=C.UTF-8
LC_CTYPE="C.UTF-8"
LC_COLLATE="C.UTF-8"
LC_TIME="C.UTF-8"
LC_NUMERIC="C.UTF-8"
LC_MONETARY="C.UTF-8"
LC_MESSAGES="C.UTF-8"
LC_ALL=
fpc:
compiled with -FcUTF-8
mormot.defines.inc inlcuded
file SOneSrv2.dpr:
Unicode text, UTF-8 (with BOM) text (also tested without BOM)
in .dpr just a writeln('ü') -> output: '?'
Thanks you,
Daniel
But it is not a regression, you are right.
With mOMRmot2 054d2568 and Free Pascal Compiler version 3.2.2 [2023/11/14] for x86_64 under FreeBSD it has same behavior.
all my units have a options.inc include with your
{$I mormot.defines.inc}
Sorry (3.2.0), Free Pascal Compiler version 3.2.0-r45643 [2021/04/13] for x86_64
../source/VendorInterface/ImportVendor/Luxottica/uLuxottica.pas: UTF-8 Unicode (with BOM) text
Just a simple writeln('ü') output a ?.
But a writeln(StringTo('ü')) outputs correct ü.
Just a question from today when working under linux (system codepage utf8), unit.pas is set to utf8 using fpc 3.2.2:
When I make a function Example(const s: RawJSON/RawUtf8/UTF8String) call with:
Example('äöü') -> it's not working any more. I have to call
Example(StringToUtf8('äöü')) to get the right string.
Is this a new behavior from this update. I can't remember to have such issues in past.
I had added a new error in my service and that's the reason of the error accumulation from today. Sorry for that.
But it seems to exists an issue before my update, so I have posted here.
The conversation was nevertheless useless, becaus my service runs now in debug mode so I'm able to give you a map file next time the issue will occur.
Thanks for your help!
I don't have a stack trace on my production system, just a log file (in verbose logging).
The mongdb call is a simple aggregate with a small result, called over a sicSingle service method. Not complex, just a very simple method.
I believe the root of the issue comes from our side, not from mORMot2. But I don't find any entries of interest in my logs.
The mongodb call methods are so simple, that there couldn't be any issue come from. I have 32 workers and every worker has its own mongodb connection in his own threadvar. No race condition, no blocking issue.
MongoDB calls are the main work in our service. If any worker connection would have an issue I would have a crash or errors instantly.
Atm I don't use your new rewrite version (just ef8764e2c).
To find out if async server is involved, should I switch to useHttpSocket and watch?
After running for days without errors, today there are ones again.
Although my service is still running, I have got an av in the log:
20250117 11262413 % EXC EOutOfMemory {Message:"Out of memory"} [R3:root] at 41c307
which comes from a call that will be called always and without issues at all. There is enough memory (45GB free of 100GB), so I guess cmem should find a free block.
I couldn't find anything interesting in log before that EXC. There is only this:
20250117 11262407 C trace mormot.net.async.THttpAsyncConnections(7f1eaaf795e0) DoGC #1=0 #2=13 free=0 client=0
But as you wrote before, nothing interesting.
@ab
today I had a crash of my service. My log shows following entry:
20250117 09214012 C trace mormot.net.async.THttpAsyncConnections(7f48913675e0) DoGC #1=0 #2=8 free=0 client=3
that could be related to
the first exception
20250117 09214037 # EXCOS EAccessViolation (8ff6e188) [R1:root] at 41c680
which comes from an harmless mongodb call.
Is it possible that DoGC (I guess it means "Do garbage collector") is the culprit?
@ab Yes mem issue is outside of pipeline.
Today we had such an issue in our program (of course without pipeline):
SOneSrv2: malloc.c:4302: _int_malloc: Assertion `(unsigned long) (size) >= (unsigned long) (nb)' failed
We had no error in Postgres log at all. But we are using cmem.
@ebekman Congrats, you're almost there! SynZip is able to decompress your data. The pascal example from @zen010101 is working.
Now you need somebody who create a pascal .dll/.so for you that can be called from your c#.
Threadvar's are created in a special memory area (thread-local storage). At compile time the addresses of that space for a thread created at runtime isn't fix.
Therefore libraries linked at compile time (which packages are) could have an issue with threadvar's. Dynamically loaded libraries are fine, because they will loaded at runtime, when the threads run.
Because of this it doesn't matter whether a threadvar is declared in interface or implementation part.
@cadnan works and is much easier than my version, thanks.
but you shouldn't forget
try
...
finally
FToken.Free;
end;
I've implemented this task some time ago to check if I could handle it. It's not so easy, but perhaps the situation is more easy if I would have a real AD.
To verify the JWT you need the public key.
The public key in pem format you get from the x5c value. In my test case (at microsoft) the key changes every time (I can't remember the interval e.g. every 30 days).
To get it you have to call -> https://login.microsoftonline.com/'+ response.tenantId +'/discovery/v2.0/keys?appid=...
and compare the kid included in the JWT which you want to verify.
If you have the public key you can verify the JWT with this func:
function VerifyJWT(const aJWT: RawByteString; const aPublicKey: RawByteString; out JWT: Variant): Boolean;
function VerifyWithmORMot(const aJWT: RawByteString; out JWT: Variant): Boolean;
var
Header, Payload, Signature: RawByteString;
sigBinary, msgBinary: TBytes;
idx, step: Integer;
aBuf: PAnsiChar;
begin
Header:= '';
Payload:= '';
Signature:= '';
idx:= 0;
step:= 0;
aBuf:= PAnsiChar(aJWT);
while aBuf[idx] <> '' do begin
INC(idx);
if aBuf[idx] = '.' then begin
INC(step);
if step=1 then
SetString(Header, aBuf, idx)
else
if step=2 then
SetString(Payload, aBuf, idx)
else
SetString(Signature, aBuf, idx);
INC(aBuf, idx+1);
idx:= 0;
end;
end;
if (idx > 0) and (step < 3) then
SetString(Signature, aBuf, idx);
JWT:= _Obj([]);
sigBinary:= Base64UrlDecode(Signature);
RawByteStringToBytes(Header+'.'+Payload, msgBinary);
Result:= OpenSslVerify('', '', Pointer(msgBinary), Pointer(aPublicKey), Pointer(sigBinary), Length(msgBinary), Length(aPublicKey), Length(sigBinary));
if Result then
JWT:= Js2Var(Base64uriToBin(PAnsiChar(Payload), Length(Payload)));
end;
begin
Result:= VerifyWithmORMot(aJWT, JWT);
end;
I've changed our code to get a stable version of our software. The errors are away.
I know there is no issue in the async/socket part of mORMot. But I don't know what exactly had cause the errors.
My guess is an issue with TSynLocker. Perhaps we haven't use it right or made some mistake in the way of lock/unlock.
I wrote again because I think it could be useful to stabilize the interfaces/network (mormot.core.interfaces / mormot.core.soa) part of the framework, so it is useful for all users:
My pov is, executing of interfaced methods isn't thread safe in some circumstances. Two parallel (sicSingle) service calls comes and their params will be mixed/override. In my case there are such corrupt bison's in mongodb queries.
@Ab could you please check TInterfaceMethodExecuteCached if there is anything what could go wrong under heaver load? All my wrk tests looks good but the live system has this error behavior and all other processes looks good, also the syslog looks good so far.
I've commented out this part of TInterfaceMethodExecuteCached .Aquire
if fCached.TryLock then
begin
// reuse this shared instance between calls
SetOptions(opt);
exec := self;
fCachedWR.CancelAllAsNew;
WR := fCachedWR;
end
but its not enough or not the right place.
Are there any other changes in past that comes with https://blog.synopse.info/?post/2022/01 … e-Them-All the that I could test easily?
Perhaps it is not an issue of wrong locking but of not initialization of something reused because of caching?
Back to the EThreadError the source comes from:
20241021 06575224 . debug uRestServerDB.TSOneRestServerDB(02eb3298) TServiceFactoryServer.InstanceFree: ignored EThreadError exception during IPersons._Release
So I would love to get further instructions from you.
Hi ab,
just fyi the error in my service from today and the syslog entries bring me to the nested option for lxc containers and I think I'll give it a try:
1. About the tags
1.1 Mainly mORMot is a server lib with features/tools you can't find in other libs. I would start the tags with those word (high performance cross-platform client/server lib for pascal).
1.2 There is a huge cryptographic part connectable with openssl you have all what anyone could want.
1.3 The handling of JSON and Variants is outstanding
1.4 The DB layer is also killer feature and the integration of Zeos makes it complete.
2. The Big Divide
Have I forget something important? Sure. But I would connect this post with The Big divide (https://synopse.info/forum/viewtopic.php?id=7027) and try to find out the main features and try to divide it when possible. So from a marketing pov it really make sense to split mORMmot in 2, 3 or 4 smaller GetIt's.
New users come mostly with specialized requirements and they don't need such a big framework/lib. Everybody of us prefer small specialized and optimized tools against huge ones (E.g. Zeos was the preferred DB-Layer for mORMmot in past, but than some reinvent the wheel and wrote his own connector for postgres -> yes, this is criticism).
So from marketing pov it really makes a difference and from a technical pov there should be solutions. So why hesitate to do it?
3. Naming
With splitting (point 2) the naming part would be much easier. But I think "mORMot" is misleading although everybody has learned to love it over the years. But are the oldies the future? No. We are talking about a bigger community, right? And therefore we have to focus on the new ones (and mostly younger ones).
ORM was a marketing thing 20 years ago. Why should we keep this name? Let us try to find a better one (or 4 better ones when divided/splitted).
4. Cross-Plattform (my initial thoughts to the last post from @cadnan)
Why hide this really great feature? We can using our software under Windows, Linux, BSD (and ARM). That's amazing! But we hide it because of Delphi? And here I see another big point:
When you @ab drink beer with Marco please suggest him to give up the Delphi compiler and just focus on a IDE for fpc. This is the way to go. Embarcadero could deliver a professional IDE for the fpc community and the open-source cross-platform compiler (fpc) does all the rest (and we all know he does it very, very good).
Atm I personally developing under Windows because of the high quality of the Delphi-IDE but just to deliver a product compiled with fpc to run on linux. That's not so efficient in my opinion.
Emba could safe much costs (I don't know how many employees work on compiler but there is sure a high potential) and sell much more units with that strategy.
Do you know this thread and is it interesting to you?
perThreadLog:= ptIdentifiedInOneFile
This one?
Here are the relevant log file entries for the EThreadError:
20241016 13290923 - 08.340.038
20241016 13290923 EXC EThreadError {Message:"Thread error"} [R16:root] at 428014
20241016 13290923 debug uRestServerDB.TSOneRestServerDB(020bafc8) TServiceFactoryServer.InstanceFree: ignored EThreadError exception during IPersons._Release
20241016 13290923 srvr 192.168.1.214 Interface POST root/Persons.GetOneByID=200 out=3 KB in 4.32s
20241016 13290923 ret mormot.rest.server.TRestServerRoutingRest(7fdb340cd238) {"result":[{"res": true, ...
The call of the sicSingle service method Persons.GetOneByID is ok from the pov of the client.
This error also comes in case of useHttpSocket (not only with useHttpAsync) and under current mORMot2 branch #38874e16c.
I've sent you an email with a log file link.
Perhaps this link is interesting for you:
https://stackoverflow.com/questions/693 … ecv-is-suc
I've also read about a hardware issue with ECC RAM but all other programs (postgres, mongodb) run without errors, so I would not go in this direction.
Yes I hope too.
This error is not really reproducible. I had it the first time since July, but we had several other errors over the last months (e.g. service not responsible or undefined exceptions or the Variant error with with _Safe(v)^.InitArrayFromCsvFile and memory corruption after that) and we have changed a lot of possible bugs on our side but without serious knowledge.
I can change logging to verbose mode and send the file to you (but it's very huge and I will give you an url for downloading per email) but also verbose logging wasn't enough in past. Perhaps adding logs in mormot.net.async or mormot.net.sock is the way to go.
If error is async related could I change to useHttpSocket for testing (in front of our service we are using nginx as reverse proxy)?
->Do you have more info?
Only this errors I had in logfile since last weeks:
20241015 15564437 EXC EThreadError {Message:"Thread error"} [R12:root]
20241015 15564446 EXC EThreadError {Message:"Thread error"} [R14:root]
20241015 15564448 EXC EThreadError {Message:"Thread error"} [R13:root]
20241015 16171856 EXC EThreadError {Message:"Thread error"} [R13:root]
20241015 16171859 EXC EThreadError {Message:"Thread error"} [R8:root]
But it seems to be transparent from the client side, because we have no error responses related to that errors.
Atm I use two services as upstream under nginx (linux as main service and a windows http.sys service as backup). The windows service seems to be more stable as the linux with async server.
->Where/when is it killed?
It's killed from os today. Here are the rows from syslog:
Oct 15 16:09:53 mssql SOneSrv2[358268]: malloc(): unaligned tcache chunk detected
Oct 15 16:09:53 mssql systemd[1]: SOneSrv2.service: Main process exited, code=killed, status=6/ABRT
Oct 15 16:09:53 mssql systemd[1]: SOneSrv2.service: Failed with result 'signal'.
Oct 15 16:09:53 mssql systemd[1]: SOneSrv2.service: Consumed 28min 29.400s CPU time.
Oct 15 16:10:23 mssql systemd[1]: SOneSrv2.service: Scheduled restart job, restart counter is at 1.
->What is the load?
It's difficult to answer.
Per day we have about 400-500 thousand requests with a average request time of 20ms, but there are also request with text search in MongoDB that could run 10s.
We are using an lxc container with 32 cores, 100G mem (60G free) and zfs. Our service has 32 worker threads and there are about 100-200 concurrent users.
The cpu-usage is mostly under 10% but for some seconds over 100% because MongoDB is heavily used in front of postgres. But I would say we don't have any overload here.
Hi Arnaud,
under Linux + fpc 3.2.0 -O3 http async (epoll) built with mORMot2 1c3447f4 (2024-09-17) and I'm using cmem.
I've got that error and our service was killed by os (ubuntu).
Is that error known and fixed in a later version?
I wouldn't change so much. My confusing results from working with your tools and not understanding much of it in depth. Some points you understand after years.
But perhaps some small improvements could help.
That _Safe could return a read only fake DocVariantData is perhaps a little bit too much and contrary to the name „_safe“.
Thanks for explaining and your patience!
A clear after each Init is necessary because Variants are managed types, right?
Otherwise the compiler would free a Variant which may be still in using because of a duplicate Init
Ok, @tbo thanks for your good and detailed article.
@ab thanks for your outstanding framework. I'm fare from any critic at all.
But I just can't find any forbidden at this (also after reading your article @tbo):
v:= _ARR([]);
_Safe(v)^.InitArrayFromCsvFile('f1,f2,f3'#10'"1";"2";"3"', [], ',','"');
It seems to work, but am I wrong?
How should I call clear here? What would clear do with an empty []?
I just ask to understand and learn, not to annoy.
Ok, but what’s wrong with a re-initialize of a variant? I could re-initialize it who often I want?
It’s only one variant on the stack and not a class-instance of a create constructor.
I create a Variant with _ARR and will fill this Variant with the data of a csv.
Is the using of _Safe(of a Variant of type 271) in this case so clearly senseless?
Can you explain a little bit. I don't know why it does make any sense.
_Safe(aVariant) gives a TDocVariantData record back and this type has the method InitArrayFromCsvFile.
Hi ab,
the using of InitArrayFromCsvFile in this context overrides memory and results in unexpected behavior:
_Safe(aVariant)^.InitArrayFromCsvFile(aRawUtf8data, [], ';', '"');
But when using a TDocVariantData I can use InitArrayFromCsvFile without issues:
aDocVariantData.InitArrayFromCsvFile(aRawUtf8data, [], ';', '"');
Do you have what's the background of that?
perhaps this info in mormot.core.text.pas can help:
// - note: mORMot 1.18 TTextWriter.RegisterCustomJSONSerializerFromText()
// are moved into Rtti.RegisterFromText() as other similar methods
P.S.
We also have contact with Ingenico
@Márcio Baroni
Thanks a lot
I'm not the one who defines which ContentType hast to be compressed. But over the last 10 years I'm using this ContentType and it was never compressed.
Should be compressing not independent from ContentTypes and compressing tagged by other headers:
Content-Type:application/json - tells what type of content data in the http call
Content-Encoding: gzip - tells what compression being used
Anyway, I need a way to disable compressing, because it isn't nice to decompress synlz compressed responses by browser/js.
Hi ab,
since commit #ebba3ec http response in browser client is compressed because of this line in mormot.net.http.pas:
compressible := IsContentTypeCompressible(pointer(OutContentType));
Do I have to set/config something to prevent this?
My ContentType is application/json.
When changing line 8903 in mormot.core.buffers.pas to this
_CONTENT_APP: array[0..4] of PUtf8Char = (
'APPLICATION/JSON', <-- this works for me
'XML',
'JAVASCRIPT',
'VND.API+JSON',
nil);
it work as expected.
Daniel