Here's piece of code doing the main thing - attaching to an active process. Although it appears that child processes have not got caught as CREATE_PROCESS_DEBUG_EVENT in the switch.
Only CREATE(EXIT)_THREAD_DEBUG_EVENT and LOAD_DLL_DEBUG_EVENT are printed in stderr, though I know exactly that sub-processes are created (not threads). Please advise.
DebugActiveProcess(processId);
DebugSetProcessKillOnExit(false);
while (!done) {
DWORD status = DBG_CONTINUE;
DEBUG_EVENT debugEvent;
WaitForDebugEvent(&debugEvent, INFINITE);
switch (debugEvent.dwDebugEventCode) {
cerr << "Got event " << debugEvent.dwDebugEventCode << endl;
case CREATE_PROCESS_DEBUG_EVENT:
{
CREATE_PROCESS_DEBUG_INFO &info = debugEvent.u.CreateProcessInfo;
cerr << "process created " << debugEvent.dwProcessId << endl;
break;
}
case EXIT_PROCESS_DEBUG_EVENT:
{
EXIT_PROCESS_DEBUG_INFO &info = debugEvent.u.ExitProcess;
cerr << "process exited" << endl;
break;
}
case LOAD_DLL_DEBUG_EVENT:
{
CloseHandle(debugEvent.u.LoadDll.hFile);
break;
}
}
ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, status);
}
The documentation at msdn.microsoft.com says: "... as if it created the process with the DEBUG_ONLY_THIS_PROCESS flag ...".
This means: When debugging a process with DebugActiveProcess all threads of the process are debugged (of course) but child processes are by not debugged.
To debug child processes too, you may set a breakpoint to the first address of CreateProcess() (to be more precise: CreateProcessA, CreateProcessW, CreateProcessAsUserA, ...). When this breakpoint is entered you modify the flags field so the process is started in suspended state and when the function returns you call DebugActiveProcess.
Related
I am using this really simple code to try to create a mutex
int main(){
HANDLE hMutex = ::CreateMutex(nullptr, FALSE, L"SingleInstanceMutex");
if(!hMutex){
wchar_t buff[1000];
_snwprintf(buff, sizeof(buff), L"Failed to create mutex (Error: %d)", ::GetLastError());
::MessageBox(nullptr, buff, L"Single Instance", MB_OK);
return 0x1;
} else {
::MessageBox(nullptr, L"Mutex Created", L"Single Instance", MB_OK);
}
return 0x0;
}
And I get the message "Mutex Created" like if it is correctly created, but when I try to search it using the tool WinObj of SysInternals I can't find it.
Also if I restart the program many times while another instance is running I always get the message "Mutex Created" and never an error because the mutex already exists.
I'm trying it on a Windows 7 VM.
What I'm doing wrong?
Ah I'm compiling on Linux using:
i686-w64-mingw32-g++ -static-libgcc -static-libstdc++ Mutex.cpp
Thank you!
In order to use a Windows mutex (whether a named one like yours or an unnamed one), you need to use the following Win APIs:
CreateMutex - to obtain a handle to the mutex Windows kernel object. In case of a named mutex (like yours) multiple processes should succeed to get this handle. The first one will cause the OS to create a new named mutex, and the others will get a handle referring to that same mutex.
In case the function succeeds and you get a valid handle to the named mutex, you can determine whether the mutex already existed (i.e. that another process already created the mutex) by checking if GetLastError returns ERROR_ALREADY_EXISTS.
WaitForSingleObject - to lock the mutex for exclusive access. This function is actually not specific to mutex and is used for many kernel objects. See the link above for more info about Windows kernel objects.
ReleaseMutex - to unlock the mutex.
CloseHandle - to release the acquired mutex handle (as usual with Windows handles). The OS will automatically close the handle when the process exists, but it is good practice to do it explicitly.
A complete example:
#include <Windows.h>
#include <iostream>
int main()
{
// Create the mutex handle:
HANDLE hMutex = ::CreateMutex(nullptr, FALSE, L"SingleInstanceMutex");
if (!hMutex)
{
std::cout << "Failed to create mutex handle." << std::endl;
// Handle error: ...
return 1;
}
bool bAlreadyExisted = (GetLastError() == ERROR_ALREADY_EXISTS);
std::cout << "Succeeded to create mutex handle. Already existed: " << (bAlreadyExisted ? "YES" : "NO") << std::endl;
// Lock the mutex:
std::cout << "Atempting to lock ..." << std::endl;
DWORD dwRes = ::WaitForSingleObject(hMutex, INFINITE);
if (dwRes != WAIT_OBJECT_0)
{
std::cout << "Failed to lock the mutex" << std::endl;
// Handle error: ...
return 1;
}
std::cout << "Locked." << std::endl;
// Do something that required the lock: ...
std::cout << "Press ENTER to unlock." << std::endl;
std::getchar();
// Unlock the mutex:
if (!::ReleaseMutex(hMutex))
{
std::cout << "Failed to unlock the mutex" << std::endl;
// Handle error: ...
return 1;
}
std::cout << "Unlocked." << std::endl;
// Free the handle:
if (!CloseHandle(hMutex))
{
std::cout << "Failed to close the mutex handle" << std::endl;
// Handle error: ...
return 1;
}
return 0;
}
Error handling:
As you can see in the documentation links above, when CreateMutex,ReleaseMutex and CloseHandle fail, you should call GetLastError to get more info about the error. WaitForSingleObject will return a specific return value upon error (see the documentation link above). This should be done as a part of the // Handle error: ... sections.
Note:
Using a named mutex for IPC (interprocess communication) might be the only good use case for native Windows mutexes.
For a regular unnamed mutex it's better to use one of the available standard library types of mutexes: std::mutex,std::recursive_mutex,std::recursive_timed_mutex (the last 2 support repeated lock by a thread, similarly to Windows mutex).
As part of my automated test suite, I have a C++ Program (A) that executes a command line Process (B) using CreateProcess().
The process only terminates when it receives a SIGINT signal (for reasons outside of my control).
I can terminate the process (B) from (A) using CloseHandle() and/or TerminateProcess(), however, this does not call the destructor of (B), preventing it from closing gracefully (writing stuff to disk and closing DB connections) and causing the tests to fail.
What is the best approach to gracefully close (B), allowing it clean up after itself? Should I be using a helper executable with IPC, a remote thread...?
I have tried the solutions in these SA questions:
Can I send a ctrl-C (SIGINT) to an application on Windows? (If I detach my console the test suite fails)
How do I send ctrl+c to a process in c#? (Modified for C+)
How to get GenerateConsoleCtrlEvent to work with cmd.exe
Edit: #Remy Lebeau is right I should have posted some code:
Current Approach:
Close the process handle. This kills the process immediately.
PROCESS_INFORMATION process_info;
... // CreateProcess()
CloseHandle(process.hProcess);
CloseHandle(process.hThread);
Approach 2:
Detach the current console and then re-attach. This causes the initial test suite to fail.
PROCESS_INFORMATION process_info;
... // CreateProcess
DWORD thisConsoleId = GetCurrentProcessId();
bool consoleDetached = (FreeConsole() != FALSE);
if (AttachConsole(process_info.dwProcessId)) {
std::cout << "Attached process to console" << std::endl;
SetConsoleCtrlHandler(NULL, true);
if (GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)) {
std::cout << "Ctrl-c sent to process" << std::endl;
} else {
std::cout << "Could not send ctrl-c (" << GetLastError() << ")" << std::endl;
}
FreeConsole();
} else {
std::cout << "Unable to attach process to console (" << GetLastError() << ")" << std::endl;
}
if (consoleDetached) {
// Create a new console if previous was deleted by OS
if (AttachConsole(thisConsoleId)) {
int errorCode = GetLastError();
// 31=ERROR_GEN_FAILURE
if (errorCode == 31) {
AllocConsole();
}
}
}
Approach 3:
Attach to console without freeing. This kills everything including the test suite.
PROCESS_INFORMATION process_info;
... // CreateProcess
AttachConsole(process_info.dwProcessId);
SetConsoleCtrlHandler(NULL, TRUE);
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
i have problem with small piece of my code.
void setTimeout(int time)
{
if (fork() == 0) {
pid_t id = getppid();
sleep(time);
if(kill(id, 0) == ESRCH)
return;
cerr << "Time out!" << endl;
kill(id, TIMEOUT);
return;
}
}
When the parent process is running and I don't need to kill him, nothing happens and it close as it should, but if parent process ends before timeout, ubuntu crashes.
Thanks for your time.
After the parent process terminates, getppid will return the process id of the shell that launched it. So you are killing the shell, which is why you drop to the login screen.
See also:
getppid() not returning parent's pid
First off: this is not a Unix/Linux system. I am working on an IBM AS/400 V7R1 (C++ 98) and do not have access to fork(). Nevertheless, I do have spawnp() to start new child processes and the AS/400 supports the notion of process groups.
In my system, I have a "head" program that starts X number of children. This head calls accept() on incoming connections and immediately gives the socket away to one of the child process via sendmsg(). The children are all sitting on recvmsg(). For the head program, it goes something like this:
rc = socketpair(AF_UNIX, SOCK_DGRAM, 0, pair_sd);
if (rc != 0) {
perror("socketpair() failed");
close(listen_sd);
exit(-1);
}
server_sd = pair_sd[0];
worker_sd = pair_sd[1];
// do some other stuff, set up arguments for spawnp()...
// ...
spawn_fdmap[0] = worker_sd;
for (int i = 0; i < numOfChildren; i++) {
pid = spawnp(spawn_argv[0], 1, spawn_fdmap, &inherit, spawn_argv, spawn_envp);
if (pid < 0) {
CERR << "errno=" << errno << ", " << strerror(errno) << endl;
CERR << "command line [";
for (int x = 0; spawn_argv[x] != 0; ++x) {
cerr << spawn_argv[x] << " ";
}
cerr << ']' << endl;
close(listen_sd);
exit(-1);
}
else {
CERR << "Child worker PID = " << pid << endl;
child_pids.push_back(pid);
}
}
// Close down the worker side of the socketpair.
close(worker_sd);
I've got a reason/scheme to start additional child processes after initial program start. I plan to send the head program some signal which would cause the spawnp() call to execute again. The "close(worker_sd)" has me concerned though. Can I call spawnp() again after I've closed the worker socket? It's just a number, after all. Is it OK to keep the worker_sd open?
Can I call spawnp() again after I've closed the worker socket?
After you called close on that socket, the file descriptor is no longer valid in this process.
You probably want a separate socketpair for each child process, so that messages from different child processes do not get interleaved/corrupted.
I think calling socketpair() for every child is unnecessary, and it means having to keep track of additional sockets on the server side. What I found is that removing the close() on 'worker_sd' allows me to create as many additional child processes as I want. Closing it and creating a child process caused the new child to die when it tried to receive something from the parent. I felt this is what would happen, and it did.
I'm trying to create a UDP broadcast program to check for local game servers, but I'm having some trouble with the receiving end. Since the amount of servers alive is unknown at all times, you must have a loop that only exits when you stop it. So in this bit of code here:
while(1) // start a while loop
{
if(recvfrom(sd,buff,BUFFSZ,0,(struct sockaddr *)&peer,&psz) < 0) // recvfrom() function call
{
cout << red << "Fatal: Failed to receive data" << white << endl;
return;
}
else
{
cout << green << "Found Server :: " << white;
cout << yellow << inet_ntoa(peer.sin_addr), htons(peer.sin_port);
cout << endl;
}
}
I wish to run this recvfrom() function until I press Ctrl + C. I've tried setting up handlers and such (from related questions), but they're all either too complicated for me, or it's a simple function that just exits the program as a demonstration. Here's my problem:
The program hangs on recvfrom until it receives a connection (my guess), so, there's never a chance for it to specifically wait for input. How can I set up an event that will work into this nicely?
Thanks!
In the CTRL-C handler, set a flag, and use that flag as condition in the while loop.
Oh, and if you're not on a POSIX systems where system-calls can be interrupted by signals, you might want to make the socket non-blocking and use e.g. select (with a small timeout) to poll for data.
Windows have a couple of problems with a scheme like this. The major problem is that functions calls can not be interrupted by the CTRL-C handler. Instead you have to poll if there is anything to receive in the loop, while also checking the "exit loop" flag.
It could be done something like this:
bool ExitRecvLoop = false;
BOOL CtrlHandler(DWORD type)
{
if (type == CTRL_C_EVENT)
{
ExitRecvLoop = true;
return TRUE;
}
return FALSE; // Call next handler
}
// ...
SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE);
while (!ExitRecvLoop)
{
fd_set rs;
FD_ZERO(&rs);
FD_SET(sd, &rs);
timeval timeout = { 0, 1000 }; // One millisecond
if (select(sd + 1, &rs, NULL, NULL, &timeout) < 0)
{
// Handle error
}
else
{
if (FD_ISSET(sd, &rs))
{
// Data to receive, call `recvfrom`
}
}
}
You might have to make the socket non-blocking for this to work (see the ioctlsocket function for how to).
Thread off your recvFrom() loop so that your main thread can wait for user input. When user requests stop, close the fd from the main thread and the recvFrom() will return immediately with an error, so allowing your recvFrom() thread to exit.