Recent

Author Topic: using RunCommand to wrap LXD linux container crashes  (Read 2112 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 8221
Re: using RunCommand to wrap LXD linux container crashes
« Reply #15 on: February 08, 2025, 01:09:43 pm »
It is correct to say that LXC and LXD are different, although the latter (LXD) rests on LXC.
To easily distinguish the 2 systems:
LXD: for image management, there is a single command  called ‘lxc’ which accepts parameters (the one I am using now in my tests)
LXC: for image management, it has a series of commands starting with ‘lxc-’, such as ‘lxc-create’, ‘lxc-attach’ and so on

Trying to sort things out for my own edification as much as anything else...

So LXD is on top of LXC, rather than the two being in some way in competition or one being a fork of the other.

Docker is at more or less the same level as LXD, although I don't believe it relies on LXC these days. I've explored this for things like FPGA development and have come up against security features which I had to relax before I could e.g. get USB port access.

Snap, AppImage etc. are at more or less the same level as Docker. I'm using these to encapsulate things like Ghidra and FreeCAD.

runc is at a lower level, looking at my desktop system I think it was pulled in as part of the basic Debian system.

Virtualisation (Qemu, KVM etc.) and paravirtualisation (UML) are of course completely distinct.

I was tempted to just stick LXC on a system until I got snared by the runc rabbithole, but I'd rather not get too deeply into it right now since I'm trying to do a hardware repair (no schematic, no silkscreened component labels...). Maybe later.

I'd note that since I routinely SSH into Docker containers it would probably be possible to have the Lazarus IDE on the host but gdbserver (accessed via a socket) in the guest/container. However in almost all cases it would be better to have the whole IDE in the guest, with either VNC or X11 piped through SSH. I'm not sure whether that has any direct relevance to your attempts to find out what LXD is doing ... ... if I had to recommend a course of action I'd suggest using TProcess as I mentioned earlier.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 8221
Re: using RunCommand to wrap LXD linux container crashes
« Reply #16 on: February 08, 2025, 01:11:08 pm »
Posts crossed but I didn't edit my last one.

At this point I would say that, at least in this case, there is a bug in RunCommand.

OK, suggest you raise a bug report. Glad that you've got something that allows you to make progress.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

nomorelogic

  • Full Member
  • ***
  • Posts: 186
Re: using RunCommand to wrap LXD linux container crashes
« Reply #17 on: February 08, 2025, 01:14:48 pm »
At this point I would say that, at least in this case, there is a bug in RunCommand.

if, using TProcess, I intercept the standard output I have the same result as RunCommand: crash at the same point.

The code:
Code: Pascal  [Select][+][-]
  1. program testlxc3;
  2. uses Classes, SysUtils, process;
  3.  
  4. const
  5.   LXC_BIN = '/usr/bin/lxc';
  6.   BUF_SIZE = 2048;
  7.  
  8. var AProcess: TProcess;
  9.     OutStream : TStream;
  10.     BytesRead    : longint;
  11.     Buffer       : array[1..BUF_SIZE] of byte;
  12. begin
  13.  
  14.   // ----------------------------------------------------
  15.   Writeln(LXC_BIN + ' LIST using TProcess');
  16.   AProcess := TProcess.Create(nil);
  17.   try
  18.     OutStream := TMemoryStream.Create;
  19.     AProcess.Executable:= LXC_BIN;
  20.     AProcess.Parameters.Add('list');
  21.     AProcess.Parameters.Add('-f');
  22.     AProcess.Parameters.Add('json');
  23.     AProcess.Options := [poUsePipes];
  24.     AProcess.Execute;
  25.  
  26.     repeat
  27.         BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);
  28.         OutStream.Write(Buffer, BytesRead)
  29.     until BytesRead = 0;
  30.  
  31.     with TStringList.Create do
  32.       begin
  33.         OutStream.Position := 0;
  34.         LoadFromStream(OutStream);
  35.         Writeln('Output (', Count, ' lines) >>');
  36.         writeln(Text);
  37.         Writeln('<< Output of "LIST"');
  38.         Free;
  39.       end;
  40.  
  41.   finally
  42.     OutStream.Free;
  43.     AProcess.Free;
  44.   end;
  45.  
  46.   Writeln('');
  47.  
  48.   // ----------------------------------------------------
  49.   Writeln(LXC_BIN + ' INIT using TProcess');
  50.   AProcess := TProcess.Create(nil);
  51.   try
  52.     OutStream := TMemoryStream.Create;
  53.     AProcess.Executable:= LXC_BIN;
  54.     AProcess.Parameters.Add('init');
  55.     AProcess.Parameters.Add('ubuntu:20.04');
  56.     AProcess.Parameters.Add('u1');
  57.     AProcess.Options := [poUsePipes];
  58.     AProcess.Execute;
  59.  
  60.     repeat
  61.         BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);
  62.         OutStream.Write(Buffer, BytesRead)
  63.     until BytesRead = 0;
  64.  
  65.     with TStringList.Create do
  66.       begin
  67.         OutStream.Position := 0;
  68.         LoadFromStream(OutStream);
  69.         Writeln('Output (', Count, ' lines) >>');
  70.         writeln(Text);
  71.         Writeln('<< Output of "INIT"');
  72.         Free;
  73.       end;
  74.  
  75.   finally
  76.     OutStream.Free;
  77.     AProcess.Free;
  78.   end;
  79.  
  80. end.
  81.  

nomorelogic

  • Full Member
  • ***
  • Posts: 186
Re: using RunCommand to wrap LXD linux container crashes
« Reply #18 on: February 08, 2025, 01:27:27 pm »
I'd note that since I routinely SSH into Docker containers it would probably be possible to have the Lazarus IDE on the host but gdbserver (accessed via a socket) in the guest/container. However in almost all cases it would be better to have the whole IDE in the guest, with either VNC or X11 piped through SSH. I'm not sure whether that has any direct relevance to your attempts to find out what LXD is doing ... ... if I had to recommend a course of action I'd suggest using TProcess as I mentioned earlier.

This of gdbserver is something I must try out.

Speaking of remote...
In the past I have also done some testing with docker and lazarus.
In this link there is a docker image made by me with xrdp + Lazarus.
https://hub.docker.com/r/nomorelogic/lazarus_184_xrdp

Once launched you can, with an RDP client, use Lazarus within the image.
I can't try it now but in the link there are instructions on how to use it.


MarkMLl

  • Hero Member
  • *****
  • Posts: 8221
Re: using RunCommand to wrap LXD linux container crashes
« Reply #19 on: February 08, 2025, 01:36:42 pm »
Once launched you can, with an RDP client, use Lazarus within the image.
I can't try it now but in the link there are instructions on how to use it.

Yes, I normally build a Debian container, SSH into it, and add the development stuff I need.

X11 through SSH normally works well, but there's an issue- possibly based on the widgetset version- where some software spends all its time polling input devices (i.e. generating lots of network traffic). In that scenario VNC (hence also RDP etc.) is a lifesaver.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 8221
Re: using RunCommand to wrap LXD linux container crashes
« Reply #20 on: February 08, 2025, 02:17:57 pm »
if, using TProcess, I intercept the standard output I have the same result as RunCommand: crash at the same point.

For the purpose of a bug report, can you distill that to something that the maintainers will almost certainly find on any Linux system?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

nomorelogic

  • Full Member
  • ***
  • Posts: 186
Re: using RunCommand to wrap LXD linux container crashes
« Reply #21 on: February 08, 2025, 07:57:06 pm »
do you mean if I can replicate the bug by avoiding using lxc?

if that is the case, I think that nothing more is needed than to install lxd.

Edit:
In the sense that the case I have is quite strange: lxc with parameter “list” works, with parameter “init” does not.
« Last Edit: February 08, 2025, 07:59:57 pm by nomorelogic »

MarkMLl

  • Hero Member
  • *****
  • Posts: 8221
Re: using RunCommand to wrap LXD linux container crashes
« Reply #22 on: February 08, 2025, 08:54:46 pm »
do you mean if I can replicate the bug by avoiding using lxc?

if that is the case, I think that nothing more is needed than to install lxd.

Edit:
In the sense that the case I have is quite strange: lxc with parameter “list” works, with parameter “init” does not.

The problem there is that the FPC developers probably won't have LXC/LXD on their systems, and it's probably not something that can be reliably tested inside another containerisation system.

Incidentally: going back to my earlier comment about shell/environment variables getting screwed (or for that matter a variable associated with RunCommand() not being restored): what happens if you swap the order? Is it  lxc init  that fails, or the second invocation of RunCommand()?

What happens if you invoke RunCommand() to run  lxc list  twice?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

nomorelogic

  • Full Member
  • ***
  • Posts: 186
Re: using RunCommand to wrap LXD linux container crashes
« Reply #23 on: February 08, 2025, 10:39:37 pm »
ok i got it
these are tests i can do

in case it will be the second execution that fails or even the second execution of the same command, I can try to replicate the crash by avoiding LXD/LXC

nomorelogic

nomorelogic

  • Full Member
  • ***
  • Posts: 186
Re: using RunCommand to wrap LXD linux container crashes
« Reply #24 on: February 10, 2025, 02:53:31 pm »
I have carried out some tests and I believe that this indicates a problem in the execution of ‘lxc’ with the ‘init’ parameter when reading the standard output

TProcess: execution of ‘lxc list’ twice (result = no crash)

Code: Pascal  [Select][+][-]
  1. program testlxc4;
  2. uses Classes, SysUtils, process;
  3.  
  4. const
  5.   LXC_BIN = '/usr/bin/lxc';
  6.   BUF_SIZE = 2048;
  7.  
  8. var AProcess: TProcess;
  9.     OutStream : TStream;
  10.     BytesRead    : longint;
  11.     Buffer       : array[1..BUF_SIZE] of byte;
  12. begin
  13.  
  14.   // ----------------------------------------------------
  15.   Writeln(LXC_BIN + ' LIST using TProcess');
  16.   AProcess := TProcess.Create(nil);
  17.   try
  18.     OutStream := TMemoryStream.Create;
  19.     AProcess.Executable:= LXC_BIN;
  20.     AProcess.Parameters.Add('list');
  21.     AProcess.Parameters.Add('-f');
  22.     AProcess.Parameters.Add('json');
  23.     AProcess.Options := [poUsePipes];
  24.     AProcess.Execute;
  25.  
  26.     repeat
  27.         BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);
  28.         OutStream.Write(Buffer, BytesRead)
  29.     until BytesRead = 0;
  30.  
  31.     with TStringList.Create do
  32.       begin
  33.         OutStream.Position := 0;
  34.         LoadFromStream(OutStream);
  35.         Writeln('Output (', Count, ' lines) >>');
  36.         writeln(Text);
  37.         Writeln('<< Output of "LIST"');
  38.         Free;
  39.       end;
  40.  
  41.   finally
  42.     OutStream.Free;
  43.     AProcess.Free;
  44.   end;
  45.  
  46.   Writeln('');
  47.  
  48.   // ----------------------------------------------------
  49.   Writeln(LXC_BIN + ' LIST using TProcess');
  50.   AProcess := TProcess.Create(nil);
  51.   try
  52.     OutStream := TMemoryStream.Create;
  53.     AProcess.Executable:= LXC_BIN;
  54.     AProcess.Parameters.Add('list');
  55.     AProcess.Parameters.Add('-f');
  56.     AProcess.Parameters.Add('json');
  57.     AProcess.Options := [poUsePipes];
  58.     AProcess.Execute;
  59.  
  60.     repeat
  61.         BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);
  62.         OutStream.Write(Buffer, BytesRead)
  63.     until BytesRead = 0;
  64.  
  65.     with TStringList.Create do
  66.       begin
  67.         OutStream.Position := 0;
  68.         LoadFromStream(OutStream);
  69.         Writeln('Output (', Count, ' lines) >>');
  70.         writeln(Text);
  71.         Writeln('<< Output of "LIST"');
  72.         Free;
  73.       end;
  74.  
  75.   finally
  76.     OutStream.Free;
  77.     AProcess.Free;
  78.   end;
  79.  
  80.  
  81. end.
  82.  
  83.  


TProcess: execution of (1) lxc init (2) lxc list (result = crash on lxc init)

Code: Pascal  [Select][+][-]
  1. program testlxc5;
  2. uses Classes, SysUtils, process;
  3.  
  4. const
  5.   LXC_BIN = '/usr/bin/lxc';
  6.   BUF_SIZE = 2048;
  7.  
  8. var AProcess: TProcess;
  9.     OutStream : TStream;
  10.     BytesRead    : longint;
  11.     Buffer       : array[1..BUF_SIZE] of byte;
  12. begin
  13.  
  14.   // ----------------------------------------------------
  15.   Writeln(LXC_BIN + ' INIT using TProcess');
  16.   AProcess := TProcess.Create(nil);
  17.   try
  18.     OutStream := TMemoryStream.Create;
  19.     AProcess.Executable:= LXC_BIN;
  20.     AProcess.Parameters.Add('init');
  21.     AProcess.Parameters.Add('ubuntu:20.04');
  22.     AProcess.Parameters.Add('u1');
  23.     AProcess.Options := [poUsePipes];
  24.     AProcess.Execute;
  25.  
  26.     repeat
  27.         BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);
  28.         OutStream.Write(Buffer, BytesRead)
  29.     until BytesRead = 0;
  30.  
  31.     with TStringList.Create do
  32.       begin
  33.         OutStream.Position := 0;
  34.         LoadFromStream(OutStream);
  35.         Writeln('Output (', Count, ' lines) >>');
  36.         writeln(Text);
  37.         Writeln('<< Output of "INIT"');
  38.         Free;
  39.       end;
  40.  
  41.   finally
  42.     OutStream.Free;
  43.     AProcess.Free;
  44.   end;
  45.  
  46.   Writeln('');
  47.  
  48.   // ----------------------------------------------------
  49.   Writeln(LXC_BIN + ' LIST using TProcess');
  50.   AProcess := TProcess.Create(nil);
  51.   try
  52.     OutStream := TMemoryStream.Create;
  53.     AProcess.Executable:= LXC_BIN;
  54.     AProcess.Parameters.Add('list');
  55.     AProcess.Parameters.Add('-f');
  56.     AProcess.Parameters.Add('json');
  57.     AProcess.Options := [poUsePipes];
  58.     AProcess.Execute;
  59.  
  60.     repeat
  61.         BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);
  62.         OutStream.Write(Buffer, BytesRead)
  63.     until BytesRead = 0;
  64.  
  65.     with TStringList.Create do
  66.       begin
  67.         OutStream.Position := 0;
  68.         LoadFromStream(OutStream);
  69.         Writeln('Output (', Count, ' lines) >>');
  70.         writeln(Text);
  71.         Writeln('<< Output of "LIST"');
  72.         Free;
  73.       end;
  74.  
  75.   finally
  76.     OutStream.Free;
  77.     AProcess.Free;
  78.   end;
  79.  
  80.  
  81. end.
  82.  


TProcess: single execution of ‘lxc init’ (result = crash)

Code: Pascal  [Select][+][-]
  1. program testlxc6;
  2. uses Classes, SysUtils, process;
  3.  
  4. const
  5.   LXC_BIN = '/usr/bin/lxc';
  6.   BUF_SIZE = 2048;
  7.  
  8. var AProcess: TProcess;
  9.     OutStream : TStream;
  10.     BytesRead    : longint;
  11.     Buffer       : array[1..BUF_SIZE] of byte;
  12. begin
  13.  
  14.   // ----------------------------------------------------
  15.   Writeln(LXC_BIN + ' INIT using TProcess');
  16.   AProcess := TProcess.Create(nil);
  17.   try
  18.     OutStream := TMemoryStream.Create;
  19.     AProcess.Executable:= LXC_BIN;
  20.     AProcess.Parameters.Add('init');
  21.     AProcess.Parameters.Add('ubuntu:20.04');
  22.     AProcess.Options := [poUsePipes];
  23.     AProcess.Execute;
  24.  
  25.     repeat
  26.         BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);
  27.         OutStream.Write(Buffer, BytesRead)
  28.     until BytesRead = 0;
  29.  
  30.     with TStringList.Create do
  31.       begin
  32.         OutStream.Position := 0;
  33.         LoadFromStream(OutStream);
  34.         Writeln('Output (', Count, ' lines) >>');
  35.         writeln(Text);
  36.         Writeln('<< Output of "INIT"');
  37.         Free;
  38.       end;
  39.  
  40.   finally
  41.     OutStream.Free;
  42.     AProcess.Free;
  43.   end;
  44.  
  45.   Writeln('');
  46.  
  47.  
  48.  
  49. end.
  50.  


TProcess: single execution of ‘docker pull’ (result = no crash)


Code: Pascal  [Select][+][-]
  1. program testlxc6;
  2. uses Classes, SysUtils, process;
  3.  
  4. const
  5.   LXC_BIN = '/usr/bin/docker';
  6.   BUF_SIZE = 2048;
  7.  
  8. var AProcess: TProcess;
  9.     OutStream : TStream;
  10.     BytesRead    : longint;
  11.     Buffer       : array[1..BUF_SIZE] of byte;
  12. begin
  13.  
  14.   // ----------------------------------------------------
  15.   Writeln(LXC_BIN + ' PULL using TProcess');
  16.   AProcess := TProcess.Create(nil);
  17.   try
  18.     OutStream := TMemoryStream.Create;
  19.     AProcess.Executable:= LXC_BIN;
  20.     AProcess.Parameters.Add('pull');
  21.     AProcess.Parameters.Add('ubuntu:latest');
  22.     AProcess.Options := [poUsePipes];
  23.     AProcess.Execute;
  24.  
  25.     repeat
  26.         BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);
  27.         OutStream.Write(Buffer, BytesRead)
  28.     until BytesRead = 0;
  29.  
  30.     with TStringList.Create do
  31.       begin
  32.         OutStream.Position := 0;
  33.         LoadFromStream(OutStream);
  34.         Writeln('Output (', Count, ' lines) >>');
  35.         writeln(Text);
  36.         Writeln('<< Output of "INIT"');
  37.         Free;
  38.       end;
  39.  
  40.   finally
  41.     OutStream.Free;
  42.     AProcess.Free;
  43.   end;
  44.  
  45.   Writeln('');
  46.  
  47.  
  48.  
  49. end.
  50.  


c++: single execution of ‘lxc init reading standard output (result = no crash)

Code: C  [Select][+][-]
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main() {
  5.     FILE *fp;
  6.     char buffer[128];
  7.  
  8.     // Run the command
  9.     // fp = popen("/usr/bin/lxc list -f json", "r");
  10.     fp = popen("/usr/bin/lxc init ubuntu:20.04", "r");
  11.     if (fp == NULL) {
  12.         perror("popen error");
  13.         return -1;
  14.     }
  15.  
  16.     // Read output a line at a time - output it.
  17.     while (fgets(buffer, sizeof(buffer), fp) != NULL) {
  18.         printf("%s", buffer); // Process the output as needed
  19.     }
  20.  
  21.     // Close the process
  22.     pclose(fp);
  23.     return 0;
  24. }
  25.  


I did all these tests with the fpc trunk.
Before reporting the bug, I'll do them again with fpc 3.2.2, I'll keep you updated.

nomorelogic

MarkMLl

  • Hero Member
  • *****
  • Posts: 8221
Re: using RunCommand to wrap LXD linux container crashes
« Reply #25 on: February 10, 2025, 03:06:16 pm »
Suggest you check that  lxc init  isn't sending its output to stderr rather than stdout.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

nomorelogic

  • Full Member
  • ***
  • Posts: 186
Re: using RunCommand to wrap LXD linux container crashes
« Reply #26 on: February 10, 2025, 08:14:56 pm »
Testet Std Error too, nothing change.

I created a new issue:
https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/41419

 

TinyPortal © 2005-2018