Archived

This topic is now archived and is closed to further replies.

Shannon Barber

FYI CreateMutex on Delphi5 is busted

Recommended Posts

And they fixed it on Delphi7 (don''t know about 6, we skipped that version). When you create a mutex, you can tell it whether or not you want it ''taken'' upon creation. In Delphi5 the mutex is never taken because they defined TRUE as $FFFFFFFF, and in the windows.h the TRUE they corresponds to BOOL is defined as 1. Then, inside of the CreateMutexW call (that CreateMutexA eventually makes), the flag is compared against 1, not against 0. By Delphi7 they added an extra function call that fixes up the flag and makes it 1 if it''s not 0. So if you use CreateMutex(..., TRUE, ...) in a Delphi5 app, you have a Race Condition in your code, because the mutex is not taken. If/when you call ReleaseMutex it will return an error indicating that the mutex is not taken. If only everybody checked all the return codes... brunt many hours on this, thought you guys might benefit from this information.

Share this post


Link to post
Share on other sites

  
procedure TForm1.Button1Click(Sender: TObject);
var
x: Integer;
y: Integer;
begin
x := Integer(LongBool(True));
y := Integer(True);

ShowMessage(Format('%x', [X]));
ShowMessage(Format('%x', [Y]));
end;


I may be wrong, but you could probably use "LongBool(True)" instead of just "True". Try it and let me know if it works.

Note: CreateMutex expects a LongBool as its second parameter, not a Boolean.

EDIT: Oops, looks like I got it back to front - sorry! Disregard this, I don't think it helps.

[edited by - Alimonster on October 18, 2002 3:09:04 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Small test project using Delphi5 :

  
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils;

Procedure _longbool(a : longbool);
begin
Writeln(Integer(a));
end;

Procedure _boolean(a : boolean);
begin
Writeln(Integer(a));
end;

begin
_longbool(true);
_boolean(true);
readln;
end.

The output is:

-1
1

Is it just be or does this NOT make sense?

CreateMutex, CreateMutexA & CreateMutexW all use the type longbool.

Share this post


Link to post
Share on other sites
It makes sense in a way (but not a sensible one). Some people use -1 for true because it''s the total opposite of 0 (i.e., 0 = $00000000 and -1 = $FFFFFFFF), but some people use 1 instead (because they think in terms of bits, 1 or 0).

quote:
A value of type ByteBool, LongBool, or WordBool is considered True when its ordinality is nonzero. If such a value appears in a context where a Boolean is expected, the compiler automatically converts any value of nonzero ordinality to True.


This seems to work:


  
program JustOne;

{$APPTYPE CONSOLE}

uses
Windows,
SysUtils;

var
H: THandle;

begin
H := CreateMutex(nil, True, ''my_lovely_mutex'');
if GetLastError = ERROR_ALREADY_EXISTS then
begin
MessageBox(0, ''Error - already running'', ''Already exists'',
MB_OK or MB_ICONHAND or MB_DEFBUTTON1);
Halt;
end;

try
WriteLn(''A test of only one instance'');
ReadLn;
finally
Win32Check(ReleaseMutex(h));
end;
end.

However, it doesn''t if you use CreateMutexW. Weird! I repeat what I said before: Weird!

Can anyone get CreateMutexW working?

Share this post


Link to post
Share on other sites
I have used CreateMutex(.., TRUE, ..) many times in D5E - It always works. Also, a search for this issue in google groups turns up nothing.

There can be ownership problems if ReleaseMutex is never called, if a program crashes in a certain way, for example.

You should try posting this to the borland.public.delphi.nativeapi newsgroup at newsgroups.borland.com

Share this post


Link to post
Share on other sites