class PollingThread : public wxThread // should actually be a singleton
{
HANDLE sem;
bool abort;
void* shared;
PollingThread(HANDLE s, void* shm) : abort(false), shared(shm)
{
sem = DuplicateHandle(s);
};
virtual int Entry()
{
for(;;)
{
WaitForSingleObject(sem, INFINITE);
if(abort)
break;
int *code = (int*) shared;
char *argv = (char*) ( ((int*) shared) +1 );
wxCommandEvent e(*code);
e.SetString(cbC2U(argv));
wxTheApp->PostMessage(e);
}
return 0;
};
void NotifyAppShutdown() // have to call this at shutdown, or the app will hang
{
abort = true;
ReleaseSemaphore(sem, 1, NULL);
};
};
class InstanceChecker
{
HANDLE hMutex;
HANDLE hSemaphore;
bool primary;
void* shared;
public:
InstanceChecker()
{
hMutex = CreateMutex (NULL, FALSE, TEXT("Code::Blocks ipc mutex"));
primary = GetLastError() == ERROR_ALREADY_EXISTS; // who am I?
hSemaphore = CreateSemaphore(NULL, 0, 1, TEXT("Code::Blocks ipc semaphore"));
if(primary)
{
HANDLE hFile = CreateFile ("/temp_path/codeblocks.ipc", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
; // uh... what to do now?
SetFilePointer(hFile, 512, 0, FILE_BEGIN); // make sure we have 512 bytes of storage
SetEndOfFile(hFile);
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, 0);
shared = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
CloseHandle(hFile);
CloseHandle(hMapping);
PollingThread t = new PollingThread(hSemaphore, shared);
t->Run();
}
else
{
// Give up time slice, for the unlikely case that two processes are started at almost exactly the same time at first run.
// In that case, we should allow the other process to create the shared memory file.
// Two full slices are ~100 ms, that should be more than enough, even in the worst of cases.
Sleep(0);
Sleep(0);
HANDLE hFile = CreateFile ("/temp_path/codeblocks.ipc", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
; // might want to retry in this case
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, 0);
shared = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
CloseHandle(hFile);
CloseHandle(hMapping);
}
};
~InstanceChecker()
{
if(shared)
UnmapViewOfFile(shared);
// Don't delete file. For one reason, it is small and being reused.
// Also, it avoids the possible race condition with several processes being launched simultaneously.
CloseHandle(hSemaphore);
CloseHandle(hMutex);
}
void DoCheck(int argc, char* argv)
{
if (primary)
return; // continue normal operation
if(argc == 0)
{
PostOtherInstance(ACTIVATE, wxEmptyString);
}
else
{
for(unsigned int i = 0; i < argc; ++i)
PostOtherInstance(OPEN, cbC2U(argv[i]));
}
wxTheApp->ExitMainLoop();
};
void PostOtherInstance(int event, const wxString& arg)
{
int *code = (int*) shared;
char *argv = (char*) ( ((int*) shared) +1 );
*code = event;
strcpy(argv, arg);
ReleaseSemaphore(hSemaphore, 1, NULL);
};
}
Does any desktop-firewall block tcp/ip traffic from and to 127.0.0.1?Yes, ZoneAlarm shows big, red warning alerts like "Code::Blocks is trying to act as a server". That does not precisely look nice.
What are the DDE problems that caused this post?
Can someone enlighten me? Thomas?
Does any desktop-firewall block tcp/ip traffic from and to 127.0.0.1?
What are the DDE problems that caused this post?Well, we're having one issue after the other (the broken batch builds being the last in a long row) and somehow every problem seems to be related in some way to either DDE directly or a change which was necessary to make DDE work. Maybe that's just my impression, but it looks to me that way. :lol:
Can someone enlighten me? Thomas?
I wonder why a desktop firewall blocks traffic that only uses 127.0.0.1 as source and destination.That is what I call SIS ("self-important software"). Firewalls and Antivirus software does that to stress its own importance. I suspect that antivirus scans are being made extra slow on purpose, too, for the same reason. You have to see that it is working hard. If there is never a network alert and a scans of your entire hard disk finishes in 5 minutes, then it can't be any good.
What are the DDE problems that caused this post?Well, we're having one issue after the other (the broken batch builds being the last in a long row) and somehow every problem seems to be related in some way to either DDE directly or a change which was necessary to make DDE work. Maybe that's just my impression, but it looks to me that way. :lol:
Can someone enlighten me? Thomas?
Well, we're having one issue after the other (the broken batch builds being the last in a long row) and somehow every problem seems to be related in some way to either DDE directly or a change which was necessary to make DDE work. Maybe that's just my impression, but it looks to me that way. :lol:
The first issue seems to have been fixed with some timed retry mods to CfgMgrBldr::Close().Eeeeeeeeh... please do not ever tamper with that function. This is absolutely no go.
QuoteThe first issue seems to have been fixed with some timed retry mods to CfgMgrBldr::Close().Eeeeeeeeh... please do not ever tamper with that function. This is absolutely no go.
Also, calling Close() will result in undefined behaviour, and will leak memory - use Free() instead. However, it is best if you don't use Free() either, since that, too, may result in undefined behaviour.
I never called Close(), it got called naturally through CfgMgrBldr::~CfgMgrBldr() when the applicated terminated. It just happened to happen at the same time in two different instances of Code::Blocks that were sending IPC messages.Ah ok, that is something we'll have to live with then, because I am not using a Windows mutex for portability (only way we could avoid that). wxWidgets mutexes don't work between processes... :(
Ah ok, that is something we'll have to live with then, because I am not using a Windows mutex for portability (only way we could avoid that). wxWidgets mutexes don't work between processes... :(
Tested. First, it tossed a "cannot find file" error at me every time. After manually removing all the stale DDE keys from the registry (the automatic uninstall does not seem to catch them all), that error was gone.
Although writing the window ID to the registry gives me a bit of a pain in the stomach, it seems to work perfectly for some files.
For some? Yes, unluckily... While all source files go into one instance just fine, XRC files and headers are opened in a separate instance.
Worse yet, if I select 10 XRC files and select "open" from Explorer's context menu, 10 instances of Code::Blocks launch in parallel, each opening one file...
So... too early for thumbs up yet, but it looks like a start :)
Actually this code snippet is almost exactly what we need (forget the DLL stuff):
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/using_shared_memory_in_a_dynamic_link_library.asp
Darn, lol... should have looked at MSDN earlier. 8)
There are some issues when the currently active window is closed and you open a file from Explorer before activating one of the other windows. The file gets stuck in the queue because noone can claim it.This is no problem at all if you use the semaphore approach instead of messaging a window. The worst thing to happen is you might lose one "open file" event, but for this to happen, you would have to hit the window's close box and open the next file within, say 0.1 seconds or so... :lol:
This is no problem at all if you use the semaphore approach instead of messaging a window.
int main(int argc, char** argv)
{
HANDLE Mutex = CreateMutex(NULL, false, _T("CodeBlocks"));
if (GetLastError() != 0) {
HWND hwndCB = 0;
while (!hwndCB) {
hwndCB = FindWindowEx(NULL, NULL, _T("CodeBlocks"), _T("CodeBlocks"));
}
// now send the commands to the handler
SendMessage();
return 0;
} else {
CreateWindow("CodeBlocks","CodeBlocks",....);
}
// now all CB stuff
CloseHandle(Mutex);
}