Possible bug on TDBEDIT on Mint - Error, SIGSEGV lazarus / 16-Databases ---------------------------------------------------------------------- incendio · 2023-11-17 03:25 Hi guys, I have this code (Lazarus 2.2.2 for  Windows 32bit, IBX 2.5.0.9999, Firebird 3) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TInpInOtFrm.DtTbl1BeforeEdit(DataSet: TDataSet);begin  if not(DM.Dt1_Ok2Edit(DtTbl1)) then Abort();end; function TDM.Dt1_Ok2Edit(DtTbl1:TIBDataset) : boolean;begin  if(DataIsLock) and not(DtTbl1.FieldByName('lck_by').IsNull) then Result := false  else Result := true;end; Those codes runs perfectly fine on Windows OS. When compiled on Linux Mint, with Lazarus 2.2.0, same version of IBX, the Abort() method raised an error : SIGSEGV. But, the same method on different event didn't raised an error. Here the code with Abort() method but still fine Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TInpInOtFrm.DtTbl1BeforePost(DataSet: TDataSet);begin  if not (DtTbl1TRS_DT.IsNull) then  begin     if not (DM.IsTrsDtValid(DtTbl1TRS_DT.AsDateTime)) then     begin        utils.Error('Not valid date!');        TrsDt.SetFocus();        Abort();     end;  end;end;  What's wrong here? ---------------------------------------------------------------------- rvk · 2023-11-17 03:45 What should Abort do?? https://www.freepascal.org/docs-html/rtl/sysutils/abort.html It raises an exception. Did you handle the exception correctly someplace else? BTW. What is DM? Is that your instance of TDM. It might be better then to remove the DM. or use Dataset.Dt1_Ok2Edit. Abort forces an exception. Usually that means an operation is halted. It might not be the best method to do this in a Lazarus application because you don't know where the exception ends up. ---------------------------------------------------------------------- incendio · 2023-11-17 03:50 Quote from: rvk on November 17, 2023, 04:45:50 amWhat should Abort do?? https://www.freepascal.org/docs-html/rtl/sysutils/abort.html It raises an exception. Did you handle the exception correctly someplace else? BTW. What is DM? Is that your instance of TDM. It might be better then to remove the DM. or use Dataset.Dt1_Ok2Edit. 1. Abort -> cancel editing, no handle exception made, should I? On Windows it is OK, also on Linux it's OK, see edited topic on post # 1 2. DM is a name of a datamodule ---------------------------------------------------------------------- rvk · 2023-11-17 03:58 PS. On the first you do it in beforeEdit. On the second in beforePost. They are different . Quote from: incendio on November 17, 2023, 04:50:24 am1. Abort -> do nothing, no handle exception made, should I? On Windows it is OK, also on Linux it's Abort forces an exception. QuoteAbort raises an EAbort exception. So where are you handling the exception? The exception can be handled differently in beforepost and beforeedit. It can even be handled differently between OSses. If you want to abort editing then you could try a Dataset.Cancel. It'll cancel the edit of the dataset and prevent anything being entered in the TDBEdit. PS. You could also try to catch the exception at the place where you are calling Dataset.Edit (if you do that manually). ---------------------------------------------------------------------- incendio · 2023-11-17 04:08 Quote from: rvk on November 17, 2023, 04:58:09 amPS. On the first you do it in beforeEdit. On the second in beforePost. If you want to abort editing then you could try a Dataset.Cancel. It'll cancel the edit of the dataset and prevent anything being entered in the TDBEdit. Tried Dataset.Cancel, only worked once, then didn't work. When tried to input text 'a' in TDBEdit, it did cancel the input, but input again, will success. BeforeEdit event not triggered again on the second attempt to edit TDBEdit. ---------------------------------------------------------------------- rvk · 2023-11-17 04:21 What happens if you only do the abort? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TInpInOtFrm.DtTbl1BeforeEdit(DataSet: TDataSet);begin  // commented out.  if not(DM.Dt1_Ok2Edit(DtTbl1)) then Abort();  Abort();end; If that's not giving you an SIGSEGV then the problem is in your code (DM.Dt1_Ok2Edit). ---------------------------------------------------------------------- incendio · 2023-11-17 04:35 Quote from: rvk on November 17, 2023, 05:21:56 amWhat happens if you only do the abort? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TInpInOtFrm.DtTbl1BeforeEdit(DataSet: TDataSet);begin  // commented out.  if not(DM.Dt1_Ok2Edit(DtTbl1)) then Abort();  Abort();end; If that's not giving you an SIGSEGV then the problem is in your code (DM.Dt1_Ok2Edit). Same error : SIGSEGV ---------------------------------------------------------------------- rvk · 2023-11-17 04:42 What exactly is DtTbl1 for component? ---------------------------------------------------------------------- incendio · 2023-11-17 04:48 Quote from: rvk on November 17, 2023, 05:42:22 amWhat exactly is DtTbl1 for component? What do you mean? It is just TIBDataset with Cache Update enabled, to receive input from users. ---------------------------------------------------------------------- rvk · 2023-11-17 04:56 Mmm, why is there a TIBDataset on your form while you also have a datamodule? Normally you have a DM for those components (although I do usually have them on my form because I have multiple instances of the same form). Anyway... OnBeforeEdit from a dataset should be able to handle exceptions. QuoteBeforeEdit is the triggered at the start of the TDataset.Edit method. The dataset is still in dsBrowse state when this event is triggered. If an exception is raised in the BeforeEdit event handler, then the dataset will remain in dsBrowse state, and the edit operation is cancelled.https://www.freepascal.org/docs- html/fcl/db/tdataset.beforeedit.html So it might be a bug. ---------------------------------------------------------------------- incendio · 2023-11-17 05:04 Quote from: rvk on November 17, 2023, 05:56:59 amMmm, why is there a TIBDataset on your form while you also have a datamodule? Normally you have a DM for those components (although I do usually have them on my form because I have multiple instances of the same form). Anyway... OnBeforeEdit from a dataset should be able to handle exceptions. QuoteBeforeEdit is the triggered at the start of the TDataset.Edit method. The dataset is still in dsBrowse state when this event is triggered. If an exception is raised in the BeforeEdit event handler, then the dataset will remain in dsBrowse state, and the edit operation is cancelled.https://www.freepascal.org/docs- html/fcl/db/tdataset.beforeedit.html So it might be a bug. A bug from IBX? Will try to inform the creator then. ---------------------------------------------------------------------- tonyw · 2023-11-17 09:05 Quote from: incendio on November 17, 2023, 06:04:19 amQuote from: rvk on November 17, 2023, 05:56:59 amMmm, why is there a TIBDataset on your form while you also have a datamodule? Normally you have a DM for those components (although I do usually have them on my form because I have multiple instances of the same form). Anyway... OnBeforeEdit from a dataset should be able to handle exceptions. QuoteBeforeEdit is the triggered at the start of the TDataset.Edit method. The dataset is still in dsBrowse state when this event is triggered. If an exception is raised in the BeforeEdit event handler, then the dataset will remain in dsBrowse state, and the edit operation is cancelled.https://www.freepascal.org/docs- html/fcl/db/tdataset.beforeedit.html So it might be a bug. A bug from IBX? Will try to inform the creator then. This is not going to be an IBX bug. TIBDataset is a subclass of TDataset (which is in the FCL) and, IBX gets involved only when TDataset.InternalEdit is called. This is called after the BeforeEdit handler runs. An exception raised in TDataset.Edit flows back to whoever called it. This may be either your code or a Data Aware control (In the LCL) which is where you should look for any dodgy exception handling. On the other hand. Sysutils.Abort() is a one liner:  Raise EAbort.Create(SAbortError) at CodePointer(Get_Caller_addr(Get_Frame)); I'm just wondering if the Windows/Linux difference is in the call to CodePointer and is due to the debug level you have compiled at. E.g. if you have not compiled in any debugging info under Linux  then maybe this call will result in a segment fault. I would replace your call to Abort with your own exception and see if you get the same result. Also, looking at your code, if seems odd that you are looking at a record field when deciding whether to abort. Remember that IBX has a record cache which is separate for each TIBDataset instance. Setting a field in one TIBDataset instance does not necessarily result in the field value being propagated to all such instances whether in the same process or another process. Firebird transaction control is a much better way to co-ordinate multiple threads working on the same data but, even here, you have to call TDataset.Post to lock a record and update the database. TDataset.Edit is not enough. ---------------------------------------------------------------------- rvk · 2023-11-17 09:59 Quote from: incendio on November 17, 2023, 05:48:08 amIt is just TIBDataset with Cache Update enabled, to receive input from users. What component switches the dataset to .Edit? TDBGrid? TDBEdit? TDBNavigator? Or something else? Or do you do it manually? In that case the exception handling is done in that component. Abort just gives an exception. It shouldn't matter if you do it yourself with Exception.Create or call Abort. The caller should handle that exception. ---------------------------------------------------------------------- incendio · 2023-11-17 10:09 Quote from: tonyw on November 17, 2023, 10:05:09 am This is not going to be an IBX bug. TIBDataset is a subclass of TDataset (which is in the FCL) and, IBX gets involved only when TDataset.InternalEdit is called. This is called after the BeforeEdit handler runs. An exception raised in TDataset.Edit flows back to whoever called it. This may be either your code or a Data Aware control (In the LCL) which is where you should look for any dodgy exception handling. On the other hand. Sysutils.Abort() is a one liner:  Raise EAbort.Create(SAbortError) at CodePointer(Get_Caller_addr(Get_Frame)); I'm just wondering if the Windows/Linux difference is in the call to CodePointer and is due to the debug level you have compiled at. E.g. if you have not compiled in any debugging info under Linux  then maybe this call will result in a segment fault. I would replace your call to Abort with your own exception and see if you get the same result. Also, looking at your code, if seems odd that you are looking at a record field when deciding whether to abort. Remember that IBX has a record cache which is separate for each TIBDataset instance. Setting a field in one TIBDataset instance does not necessarily result in the field value being propagated to all such instances whether in the same process or another process. Firebird transaction control is a much better way to co-ordinate multiple threads working on the same data but, even here, you have to call TDataset.Post to lock a record and update the database. TDataset.Edit is not enough. I don't know much about Lazarus, all I have done is untick Generate debuging info in project option. Do you have any hints what parameters should be set in Linux? My goal is, if column lck_by is not null, then cancel editing from users. Dataset.Cancel seem able to solved this, unfortunately, event BeforeEdit only triggered once, after a call to Dataset.Cancel, it won't call again, hence I use Abort with is fine in Windows. How to use IBX's record cache to achieve my goal? ---------------------------------------------------------------------- incendio · 2023-11-17 10:14 Quote from: rvk on November 17, 2023, 10:59:17 amQuote from: incendio on November 17, 2023, 05:48:08 amIt is just TIBDataset with Cache Update enabled, to receive input from users. What component switches the dataset to .Edit? TDBGrid? TDBEdit? TDBNavigator? Or something else? Or do you do it manually? In that case the exception handling is done in that component. Abort just gives an exception. It shouldn't matter if you do it yourself with Exception.Create or call Abort. The caller should handle that exception. Not sure understand your question. Here's what happen : 1. Users opened previously saved data. 2. After data displayed to users,  users click TDbEdit and start typing, this will fire up BeforeEdit event. ---------------------------------------------------------------------- rvk · 2023-11-17 10:19 Quote from: incendio on November 17, 2023, 11:14:01 am2. After data displayed to users,  users click TDbEdit and start typing, this will fire up BeforeEdit event. That was what I was asking. Your TDBEdit switches the Dataset to Edit. BTW. I would use Datasource.OnStateChange for checking if you can edit the record. Not Dataset.BeforeEdit. The upside of Datasource.OnStateChange is that you can also catch insert etc. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TDocument.srDocStateChange(Sender: TObject);begin    if (TDatasource(Sender).Dataset.State in [dsInsert, dsEdit]) then // ERROR? // you could also just use tbDoc.State instead of Sender    begin// etc.. Maybe that one doesn't crash in Mint. ---------------------------------------------------------------------- incendio · 2023-11-17 10:24 Quote from: rvk on November 17, 2023, 11:19:51 amQuote from: incendio on November 17, 2023, 11:14:01 am2. After data displayed to users,  users click TDbEdit and start typing, this will fire up BeforeEdit event. That was what I was asking. Your TDBEdit switches the Dataset to Edit. BTW. I would use Datasource.OnStateChange for checking if you can edit the record. Not Dataset.BeforeEdit. The upside of Datasource.OnStateChange is that you can also catch insert etc. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TDocument.srDocStateChange(Sender: TObject);begin    if (TDatasource(Sender).Dataset.State in [dsInsert, dsEdit]) then // ERROR? // you could also just use tbDoc.State instead of Sender    begin// etc.. Maybe that one doesn't crash in Mint. Good info, thanks,  will try it when in front of computer. ---------------------------------------------------------------------- rvk · 2023-11-17 13:09 Quote from: incendio on November 17, 2023, 11:24:35 amGood info, thanks,  will try it when in front of computer. PS. The complete start of the code I have in my program is like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TDocument.srDocStateChange(Sender: TObject);begin   if OnlyReadAllowed then  begin    if (tbDoc.State in [dsInsert, dsEdit]) then // ERROR?  begin      tbDoc.Cancel;      if tbDoc.Transaction.InTransaction then          tbDoc.Transaction.RollbackRetaining;    end;  end;   //... some extra code for enabling save buttons etc.  This will prevent any component from switching the Datasource to dsEdit or dsInsert. And works perfectly with all TDBEdits and TDBGrids. ---------------------------------------------------------------------- incendio · 2023-11-19 01:46 Quote from: rvk on November 17, 2023, 02:09:24 pmQuote from: incendio on November 17, 2023, 11:24:35 amGood info, thanks,  will try it when in front of computer. PS. The complete start of the code I have in my program is like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TDocument.srDocStateChange(Sender: TObject);begin   if OnlyReadAllowed then  begin    if (tbDoc.State in [dsInsert, dsEdit]) then // ERROR?  begin      tbDoc.Cancel;      if tbDoc.Transaction.InTransaction then          tbDoc.Transaction.RollbackRetaining;    end;  end;   //... some extra code for enabling save buttons etc.  This will prevent any component from switching the Datasource to dsEdit or dsInsert. And works perfectly with all TDBEdits and TDBGrids. This solution kind of solved the problem in Linux Mint, it didn't crash, but raised another problem. Cancel method seem didn't halt the application. After Cancel issued, execution of next codes continued and here is the problem. Sometimes, there is some condition must be meet before able to successfully execute next code. For example, there are 3 Fields, Field A, B & C. Field C will calculate Field B/Field A. If there is Cancel method issued on Field A, since execution will still continue, error will be raised. This is different with Abort method. When Abort issued, code to calculate Field C won't be execute. Of course, another checking codes could be added to check for certain condition, but because there are lots of events that will be affected by OnStageChange, application complexity grows. ---------------------------------------------------------------------- rvk · 2023-11-19 07:52 Quote from: incendio on November 19, 2023, 02:46:53 amCancel method seem didn't halt the application. After Cancel issued, execution of next codes continued and here is the problem. Sometimes, there is some condition must be meet before able to successfully execute next code. I'm not sure what exactly you are doing in code but that's just a code flow problem. I've never had that problem. If you don't want to check the state in a calculate event you could see if calling raise/abort in statechange after the cancel would help. Otherwise you need to show some small example code which would reproduce your problem (preferably a complete small test project). ---------------------------------------------------------------------- incendio · 2023-11-19 08:30 Quote from: rvk on November 19, 2023, 08:52:09 amQuote from: incendio on November 19, 2023, 02:46:53 amCancel method seem didn't halt the application. After Cancel issued, execution of next codes continued and here is the problem. Sometimes, there is some condition must be meet before able to successfully execute next code. I'm not sure what exactly you are doing in code but that's just a code flow problem. I've never had that problem. If you don't want to check the state in a calculate event you could see if calling raise/abort in statechange after the cancel would help. Otherwise you need to show some small example code which would reproduce your problem (preferably a complete small test project). OK, will try to create small project to demonstrate the problem. ---------------------------------------------------------------------- incendio · 2023-11-20 02:27 Quote from: rvk on November 19, 2023, 08:52:09 amI'm not sure what exactly you are doing in code but that's just a code flow problem. I've never had that problem. If you don't want to check the state in a calculate event you could see if calling raise/abort in statechange after the cancel would help. Otherwise you need to show some small example code which would reproduce your problem (preferably a complete small test project). Here is the sample project with Firebird database. Thanks for your help, appreciated. ---------------------------------------------------------------------- rvk · 2023-11-20 03:35 Quote from: incendio on November 20, 2023, 03:27:20 amHere is the sample project with Firebird database. I can have a look at it later this morning (it's night now). But can you explain the exact problem again. I don't see a calculated field, only you adding two values before an edit. BTW. Have you tried an Abort after the showmessage in statechange? (I would never work with Abort like this. You need to anticipate the Post failing in a proper way  and not rely on an exception to dictate code flow.) ---------------------------------------------------------------------- incendio · 2023-11-20 03:50 Quote from: rvk on November 20, 2023, 04:35:41 amQuote from: incendio on November 20, 2023, 03:27:20 amHere is the sample project with Firebird database. I can have a look at it later this morning (it's night now). But can you explain the exact problem again. I don't see a calculated field, only you adding two values before an edit. BTW. Have you tried an Abort after the showmessage in statechange? (I would never work with Abort like this. You need to anticipate the Post failing in a proper way  and not rely on an exception to dictate code flow.) Take your time, no hurry. The problem is on the Append method, this method will fire OnStateChange and NewRecord events. On event OnStateChange, dataset was cancel, then process continued to NewRecord event, where the new value to field Id is assigned. This NewRecord event raised an error : not in edit mode. This is understanable, since dataset is in dsbrowse state after Cancel method called. Like I said before, Cancel method will not halt the next process, that is why NewRecord event still fire up. This is different with Abort. Abort stop next process. Of course, I can add codes in NewRecord to add another checking, but since OnStateChange scope is large, it mean every procedures / functions that affected by OnStateChange must be evaluated again. ---------------------------------------------------------------------- rvk · 2023-11-20 09:51 Quote from: incendio on November 20, 2023, 04:50:33 amThe problem is on the Append method, this method will fire OnStateChange and NewRecord events.Yes, but that's easilly solved by putting an raise or Abort in OnStateChange. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i TDataSource(Sender).DataSet.Cancel;ShowMessage('Can not edit!');Abort; Do note that this code can also run into an exception which you need to handle. .Post can also fail and it's better to show a proper message instead of an exception. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   if (Dt2.State = dsEdit) or (Dt2.State = dsInsert) then Dt2.Post();  Edit1.Text:=(Dt2NUM1.AsInteger +Dt2NUM2.AsInteger).ToString();  ShowMessage(Edit1.Text);  Dt2.Append; ---------------------------------------------------------------------- incendio · 2023-11-20 10:00 Quote from: rvk on November 20, 2023, 10:51:09 amQuote from: incendio on November 20, 2023, 04:50:33 amThe problem is on the Append method, this method will fire OnStateChange and NewRecord events.Yes, but that's easilly solved by putting an raise or Abort in OnStateChange. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i TDataSource(Sender).DataSet.Cancel;ShowMessage('Can not edit!');Abort; Do note that this code can also run into an exception which you need to handle. .Post can also fail and it's better to show a proper message instead of an exception. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   if (Dt2.State = dsEdit) or (Dt2.State = dsInsert) then Dt2.Post();  Edit1.Text:=(Dt2NUM1.AsInteger +Dt2NUM2.AsInteger).ToString();  ShowMessage(Edit1.Text);  Dt2.Append;That's the real problem. Abort on Linux Mint raised an error SIGSEGV. On Windows Abort is OK & enough if it is put in BeforeEdit event, no need for Cancel. On Mint, Lazarus ver I installed from Software Manager was ver 2.2.0, not the latest version. Will try to install ver 3 on mint, probably the error is gone. ---------------------------------------------------------------------- rvk · 2023-11-20 10:03 Quote from: incendio on November 20, 2023, 11:00:31 amThat's the real problem. Abort on Linux Mint raised an error SIGSEGV.Ok, did it also raise an SIGSEGV exception when you used it in OnStateChange? (Because that's a different place from BeforeEdit and I thought it should/could work there) ---------------------------------------------------------------------- incendio · 2023-11-20 10:05 Quote from: rvk on November 20, 2023, 11:03:04 amQuote from: incendio on November 20, 2023, 11:00:31 amThat's the real problem. Abort on Linux Mint raised an error SIGSEGV.Ok, did it also raise an SIGSEGV exception when you used it in OnStateChange? (Because that's a different place from BeforeEdit and I thought it should/could work there) Don't know, already un-installed Lazarus 2.2.0, will try on ver 3. ---------------------------------------------------------------------- tonyw · 2023-11-20 12:12 Quote from: incendio on November 17, 2023, 11:09:49 amQuote from: tonyw on November 17, 2023, 10:05:09 am This is not going to be an IBX bug. TIBDataset is a subclass of TDataset (which is in the FCL) and, IBX gets involved only when TDataset.InternalEdit is called. This is called after the BeforeEdit handler runs. An exception raised in TDataset.Edit flows back to whoever called it. This may be either your code or a Data Aware control (In the LCL) which is where you should look for any dodgy exception handling. On the other hand. Sysutils.Abort() is a one liner:  Raise EAbort.Create(SAbortError) at CodePointer(Get_Caller_addr(Get_Frame)); I'm just wondering if the Windows/Linux difference is in the call to CodePointer and is due to the debug level you have compiled at. E.g. if you have not compiled in any debugging info under Linux  then maybe this call will result in a segment fault. I would replace your call to Abort with your own exception and see if you get the same result. Also, looking at your code, if seems odd that you are looking at a record field when deciding whether to abort. Remember that IBX has a record cache which is separate for each TIBDataset instance. Setting a field in one TIBDataset instance does not necessarily result in the field value being propagated to all such instances whether in the same process or another process. Firebird transaction control is a much better way to co-ordinate multiple threads working on the same data but, even here, you have to call TDataset.Post to lock a record and update the database. TDataset.Edit is not enough. I don't know much about Lazarus, all I have done is untick Generate debuging info in project option. Do you have any hints what parameters should be set in Linux? My goal is, if column lck_by is not null, then cancel editing from users. Dataset.Cancel seem able to solved this, unfortunately, event BeforeEdit only triggered once, after a call to Dataset.Cancel, it won't call again, hence I use Abort with is fine in Windows. How to use IBX's record cache to achieve my goal? If you have unticked "Generate Debugging Info" in the project options then I am not surprised to see a call to Abort() fail with a segment fault. Suggest you replace with your own exception e.g. raise Exception.Create("My abort message"); ---------------------------------------------------------------------- incendio · 2023-11-21 03:06 Quote from: rvk on November 20, 2023, 11:03:04 amQuote from: incendio on November 20, 2023, 11:00:31 amThat's the real problem. Abort on Linux Mint raised an error SIGSEGV.Ok, did it also raise an SIGSEGV exception when you used it in OnStateChange? (Because that's a different place from BeforeEdit and I thought it should/could work there) Tried it on Lazarus Linux 2.2.6, same error : SIGSEGV ---------------------------------------------------------------------- incendio · 2023-11-21 03:09 Quote from: tonyw on November 20, 2023, 01:12:25 pmIf you have unticked "Generate Debugging Info" in the project options then I am not surprised to see a call to Abort() fail with a segment fault. Suggest you replace with your own exception e.g. raise Exception.Create("My abort message"); Still got error SIGSEGV Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Dt1BeforeEdit(DataSet: TDataSet);begin  if DataIsLock then  begin    raise Exception.Create('Can not Edit');  end;end;  Btw, IBX could not be installed on Lazarus 3, tried it via online Package Manager. ---------------------------------------------------------------------- rvk · 2023-11-21 07:46 Quote from: incendio on November 21, 2023, 04:09:02 amBtw, IBX could not be installed on Lazarus 3, tried it via online Package Manager. No, even IBX trunk doesn't compile in Lazarus trunk. You need to add a nil at the place where you get the error. (Datatype) BTW. Does the small testproject also crash? I'll see if I can try it on mint later today. ---------------------------------------------------------------------- incendio · 2023-11-21 08:25 Quote from: rvk on November 21, 2023, 08:46:06 amQuote from: incendio on November 21, 2023, 04:09:02 amBtw, IBX could not be installed on Lazarus 3, tried it via online Package Manager. No, even IBX trunk doesn't compile in Lazarus trunk. You need to add a nil at the place where you get the error. (Datatype) BTW. Does the small testproject also crash? I'll see if I can try it on mint later today. Yes, small project gave same error. ---------------------------------------------------------------------- rvk · 2023-11-21 08:54 Quote from: tonyw on November 20, 2023, 01:12:25 pm.. @tonyw. Besides the missing datatype in trunk the last time I compiled, I now also got an error when downloading the latest IBX via trunk in SVN. The missing files prevent installation totally. Edit: Now it seems to be working again... (10:10) Edit #2: On Linux it still happened. After a svn cleanup ibx and a second try it did work. (The missing datatype seems to be fixed in the latest trunk) Command: Code: Bash  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i svn co https://svn.mwasoftware.co.uk/public/ibx/trunk ibx On Windows: Quote... A    ibx\examples\DBAdmin\dlg\DBLoginDlgUnit.lfm A    ibx\examples\DBAdmin\dlg\NewUserDlgUnit.lfm A    ibx\examples\DBAdmin\dlg\ShutdownDatabaseDlgUnit.lfm svn: E175013: Access to '/public/!svn/rvr/380/ibx/trunk/examples/DBAdm in/dlg/BackupDlgUnit.lfm' forbidden On Linux: Quote... A    ibx/examples/scriptengine/unit2.pas A    ibx/examples/scriptengine/tests/createproc.sql A    ibx/examples/scriptengine/unit2.lfm svn: E175013: Access to '/public/!svn/rvr/421/ibx/trunk/examples/employee/unit1.pas' forbidden svn: E200042: Additional errors: svn: E175013: Access to '/public/!svn/rvr/410/ibx/trunk/examples/fbsql/buildAndInstall.sh' forbidden svn: E175013: Access to '/public/!svn/rvr/380/ibx/trunk/examples/ibstoredproc/Unit1.lfm' forbidden svn: E175013: Access to '/public/!svn/rvr/158/ibx/trunk/examples/ibstoredproc/fbout-body.sql' forbidden svn: E175013: Access to '/public/!svn/rvr/380/ibx/trunk/examples/ibsto redproc/ibstoredprocdemo.lpi' forbidden After that, there are a lot of files missing, not just in example. ---------------------------------------------------------------------- rvk · 2023-11-21 14:01 The problem is not in IBX or even in TDataset. The problem is in the Edit components. I changed the sample project to just do a .Edit and Abort in BeforeEdit and that worked just fine. When adding a TDBEdit it crashed. The Abort itself worked fine but when typing text afterwards in the TDBEdit you get the SIGSEGV. Somehow the TDBEdit keeps hanging in an edit state and creates the SIGSEGV. The Abort should be the correct way to cancel the operation. SQLdb does this internally itself too. The Abort will be silent (EAbort) and the operation is cancelled. But somehow the visual control crashes at that moment (only on Linux). So it's a bug in SQLdb. ---------------------------------------------------------------------- incendio · 2023-11-21 15:53 Quote from: rvk on November 21, 2023, 03:01:12 pmThe problem is not in IBX or even in TDataset. The problem is in the Edit components. I changed the sample project to just do a .Edit and Abort in BeforeEdit and that worked just fine. When adding a TDBEdit it crashed. The Abort itself worked fine but when typing text afterwards in the TDBEdit you get the SIGSEGV. Somehow the TDBEdit keeps hanging in an edit state and creates the SIGSEGV. The Abort should be the correct way to cancel the operation. SQLdb does this internally itself too. The Abort will be silent (EAbort) and the operation is cancelled. But somehow the visual control crashes at that moment (only on Linux). So it's a bug in SQLdb. I'm confused, where is the bug, TDBEdit or SQLdb? ---------------------------------------------------------------------- rvk · 2023-11-21 16:01 Quote from: incendio on November 21, 2023, 04:53:49 pmI'm confused, where is the bug, TDBEdit or SQLdb? Sorry, not SQLdb... I think in TDBEdit (but I'm not a core programmer). I think, somehow, during entering a character in the TDBEdit, the refcount for TDBEdit is decreased to 0 (due to the Abort ??) after which the TDBEdit component is freed (which gives a SIGSEGV exception). But I can't precisely pinpoint how and where. It's not a bug in FPC or SQLdb because you can freely do a Dataset.Edit and BeforeEdit executes and the dataset stays in dsBrowse because of the Abort. All that doesn't cause the crash. The crash only occurs when you type in a TDBEdit afterwards (when the Dataset is switched to Edit by the DataLink from the TDBEdit). ---------------------------------------------------------------------- rvk · 2023-11-21 16:24 I do have a possible solution for you. In stead of using the BeforeEdit and doing an Abort you can use the AfterEdit and do a Cancel on the Dataset. This worked for me in my adjusted sample program: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Dt1AfterEdit(DataSet: TDataSet);begin  if DataIsLock then    Datsaet.Cancel;end; BTW. It's also really confusing that you switch the dataset of ActDS datasource when switching the Groupbox. Just add the same eventhandler to Dt1.AfterEdit to Dt2.AfterEdit. They can point to the same eventhandler and you can use "Dataset" to do your handlings on. ---------------------------------------------------------------------- incendio · 2023-11-22 03:38 Quote from: rvk on November 21, 2023, 05:24:42 pmI do have a possible solution for you. In stead of using the BeforeEdit and doing an Abort you can use the AfterEdit and do a Cancel on the Dataset. This worked for me in my adjusted sample program: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Dt1AfterEdit(DataSet: TDataSet);begin  if DataIsLock then    Datsaet.Cancel;end; BTW. It's also really confusing that you switch the dataset of ActDS datasource when switching the Groupbox. Just add the same eventhandler to Dt1.AfterEdit to Dt2.AfterEdit. They can point to the same eventhandler and you can use "Dataset" to do your handlings on. Thank for your help. When DataIsLock, I don't wan't users to edit/insert or delete record. With your method, I pointed All Dataset.AfterEdit & Dataset.AfterInsert to the same event handler, this worked OK, except for delete record. Although AfterDelete or BeforeDelete pointed to the same handler in AfterEdit event, record still deleted. So for delete event, I adjusted the code into like these, this is also answering your question about the use of switching ActDs.Dataset (in my app, users must put mouse location in TDBEdit/TDBGrid to choose which record will be deleted) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.btnDelClick(Sender: TObject);begin  if (DataIsLock) and (ActDS.DataSet =Dt2) then exit;  if ActDS.DataSet =Dt1 then Dt1.Delete  else Dt2.Delete;end; I think, this is the best solution for now, thanks again. So, if this a bug in TDBEdit, I will change Thread's Title so others will be aware of this bug in Linux. ---------------------------------------------------------------------- egsuh · 2023-11-22 07:55 If the purpose is to prohibit users to edit a field for records with certain conditions, I would set the DBEdit as readonly in AfterScroll event handler.    Dt1_Ok2Edit.ReadOnly := DataIsLock or DtTbl1.FieldByName('lck_by').IsNull; Why Abort causes SEGSIV error? I do not care...  I just use Windows. ---------------------------------------------------------------------- incendio · 2023-11-22 08:48 Quote from: egsuh on November 22, 2023, 08:55:06 amIf the purpose is to prohibit users to edit a field for records with certain conditions, I would set the DBEdit as readonly in AfterScroll event handler.    Dt1_Ok2Edit.ReadOnly := DataIsLock or DtTbl1.FieldByName('lck_by').IsNull; Why Abort causes SEGSIV error? I do not care...  I just use Windows. OK, thanks for your hint, case closed 👍