• Forum
  • Lounge
  • Just managed to write my first fork bomb

 
Just managed to write my first fork bomb...

I didn’t mean to, of course.

The lesson here is to always test first by print what you are going to do before enabling the code to create a new process.

I thought modern OSes could identify and terminate such processes...
Maybe mine was odd enough to overcome that?
(After calling CreateProcess my process terminates, so there is really only a few instances of my app running at any given point in time.)

Gonna fix that now...
"To err is human....

"...to really screw things up use a computer."

BTDT what you experienced, D. I still will have it happen in the future.
Quoting Abraham Lincoln on the internet. Nice!

[edit]
Lesson 2: it was an off-by-one error.

My app can process multiple 'sessions', but each app can only handle one session itself. So it just clones itself for each remaining session.

A session is indicated via command-line argument. So I take a command line like:

    Example1 a b c --session=A 1 2 --session=B 3 4 -- d e f

and treat it as:

    Example1 a b c --session=A 1 2 -- d e f
    Example1 a b c --session=B 3 4 -- d e f

App handles session A itself, but uses CreateProcess to handle session B.

My command-line parsing accidentally kept including session A in the new command-line, because when I scanned the argument list for sessions, I did something that boils down to this:

1
2
int index1 = find_session( 0 );
int index2 = find_session( index1 );

when I should have written this:

1
2
int index1 = find_session( 0 );
int index2 = find_session( index1+1 );

LOL.
Last edited on
Making simple errors like that truly is my specialty! :D

Trying to install some package using vcpkg without actually issuing the install command, only the app and package name(s). Ooooops!
Trying (badly) to create a github repository, way-oh!

Yeah, I know, I'm behind the curve with all this internet stuff.

https://github.com/GeorgePimpleton
> I'm behind the curve with all this internet stuff.

Using a GUI client may make the learning curve less steep.
Sourcetree (Git and Hg): https://www.sourcetreeapp.com/
GitKraken: https://www.gitkraken.com/
I did get git for windows which has a GUI client along with Git Bash. Plus I installed TortoisGit as well. Also downloaded the free Pro Git PDF, started reading it today.

I downloaded the git for windows so I could use vcpkg.

I am now just wandering the deep, dark forest that is git.

I do thank you for the suggestions JL. :)
The more I use Github the more I seem to hate it. There's a lot of nuances that I wish I didn't have to deal with. Not to mention the number of times it would just fail and I'd have to delete all my files, redo the fork, etc..

Using the GUI version of Github got old pretty fast and I went back to command line.
So far my experience with github hasn't been unpleasant, any problems have been user errors.

Not that I am doing a lot of work that is mission critical. If something goes wrong at their end it isn't the end of the world, not a lot of work is lost since I have everything in a local repository.

The only command-line problem I have is when I do a commit. I type the command and get an editor in the Win command prompt/Bash. Well, I'm kinda off into the rough instead of the fairway.

I know there are other git repository hosting services available, I'm stickin' w/ github since vcpkg uses github, and if my programming books have online source code available it is on github.

Today I learned that the order of elements in an interface declaration matters. IDK why I thought dispatch would figure it out. (I admit all I ever did was skim through the COM/OLE parts of the manual.)

Here’s what I was using to play with it. (I’ve since added a whole bunch of junk to test every function, and am now considering wrapping the interface in a less type-stupid TInterfacedObject class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
unit Unit1;

{$mode objfpc}{$H+}

///////////////////////////////////////////////////////////////////////////////////////////////////
interface
///////////////////////////////////////////////////////////////////////////////////////////////////

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtDlgs;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;


///////////////////////////////////////////////////////////////////////////////////////////////////
implementation
///////////////////////////////////////////////////////////////////////////////////////////////////

{$R *.lfm}

uses
  Windows, ActiveX, ShlObj, ComObj;

// ORDER is important when declaring the interface -- everything must match EXACTLY
// https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/um/ShObjIdl_core.h
// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-idesktopwallpaper

const
  CLSID_DesktopWallpaper : TCLSID = '{C2CF3110-460E-4FC1-B9D0-8A1C0C9CC4BD}';
  SID_DesktopWallpaper            = '{B92B56A9-8B55-4E14-9A89-0199BBB6F93B}';

type
  PIShellItemArray = ^IShellItemArray;

  {$Z4}
  DESKTOP_SLIDESHOW_OPTIONS =
  (
    DSO_DEFAULT       = $0,
    DSO_SHUFFLEIMAGES = $1
  );

  DESKTOP_SLIDESHOW_STATE =
  (
    DSS_ENABLED                    = $1,
    DSS_SLIDESHOW                  = $2,
    DSS_DISABLED_BY_REMOTE_SESSION = $4
  );

  DESKTOP_SLIDESHOW_DIRECTION =
  (
    DSD_FORWARD  = 0,
    DSD_BACKWARD = 1
  );

  DESKTOP_WALLPAPER_POSITION =
  (
    DWPOS_CENTER  = 0,
    DWPOS_TILE    = 1,
    DWPOS_STRETCH = 2,
    DWPOS_FIT     = 3,
    DWPOS_FILL    = 4,
    DWPOS_SPAN    = 5
  );

  IDesktopWallpaper = interface( IUnknown )
    [SID_DesktopWallpaper]
    procedure SetWallpaper( monitorID:PWideChar; wallpaper:PWideChar ); safecall;
    function  GetWallpaper( monitorID:PWideChar ): PWideChar; safecall;
    function  GetMonitorDevicePathAt( monitorIndex:LongWord ): PWideChar; safecall;
    function  GetMonitorDevicePathCount: LongWord; safecall;
    function  GetMonitorRECT( monitorID:PWideChar ): TRect; safecall;
    procedure SetBackgroundColor( color:COLORREF ); safecall;
    function  GetBackgroundColor: COLORREF; safecall;
    procedure SetPosition( position:DESKTOP_WALLPAPER_POSITION ); safecall;
    function  GetPosition: DESKTOP_WALLPAPER_POSITION; safecall;
    procedure SetSlideshow( items:PIShellItemArray ); safecall;
    function  GetSlideshow: PIShellItemArray; safecall;
    procedure SetSlideshowOptions( options:DESKTOP_SLIDESHOW_OPTIONS; slideshowTick:LongWord ); safecall;
    procedure GetSlideshowOptions( out options:DESKTOP_SLIDESHOW_OPTIONS; out slideshowTick:LongWord ); safecall;
    procedure AdvanceSlideShow( monitorID:PWideChar; direction:DESKTOP_SLIDESHOW_DIRECTION ); safecall;
    function  GetStatus: DESKTOP_SLIDESHOW_STATE; safecall;
    procedure Enable( enable:LongBool ); safecall;
  end;


function CopyAndCoTaskMemFree( s:PWideChar ): WideString;
  begin
    result := s;
    CoTaskMemFree( s )
  end;


procedure TForm1.Button1Click(Sender: TObject);
  var
    Wallpaper    : IDesktopWallpaper;
    MonitorCount : Integer;
    n            : Integer;
    MonitorPath  : WideString;
    PicturePath  : WideString;

  begin
    Memo1.Lines.Clear;
    try
      Wallpaper := CreateComObject( CLSID_DesktopWallpaper ) as IDesktopWallpaper;
      Memo1.Lines.Add( 'IDesktopWallpaper instance created' );

      try
        // Single picture on all monitors
        PicturePath := CopyAndCoTaskMemFree( Wallpaper.GetWallpaper( nil ) );
        Memo1.Lines.Add( '(Single picture on all monitors)' );
        Memo1.Lines.Add( 'file = ' + String(PicturePath) );

      finally
        MonitorCount := Wallpaper.GetMonitorDevicePathCount;
        Memo1.Lines.Add( 'monitor count = ' + IntToStr( MonitorCount ) );

        for n := 0 to MonitorCount-1 do
          begin
            Memo1.Lines.Add( IntToStr( n ) + ':' );

            MonitorPath := CopyAndCoTaskMemFree( Wallpaper.GetMonitorDevicePathAt( n ) );
            Memo1.Lines.Add( '  monitor id = ' + String(MonitorPath) );

            PicturePath := CopyAndCoTaskMemFree( Wallpaper.GetWallpaper( PWideChar(MonitorPath) ) );
            Memo1.Lines.Add( '  file path = ' + String(PicturePath) );
          end
      end

    except
      on E:EOleError do ShowMessage( E.Message )
    end;

    Wallpaper := nil
  end;                              

If you have a copy of Lazarus/FPC lying around just create a new project, drop a button and a memo on the blank form, add an OnClick event to the button, and copy and paste into unit1.pas.

If you are rich enough to have a copy of Delphi lying around, you will also need to change that resource directive to {$R *.dfm}. I’m pretty sure that’s it. (My copy of D5 is too old to compile this properly.)
Last edited on
Topic archived. No new replies allowed.