I am setting a PLOAD_IMAGE_NOTIFY_ROUTINE to detect a specific image name and if there's a match, then terminate it. I am getting a KERNEL_APC_PENDING_DURING_EXIT BSOD though. The BSOD is happening somewhere in my KillProcess function which simply just opens a kernel handle with ObOpenObjectByPointer then calls ZwTerminateProcess on that handle.
What could be wrong? The code works fine outside the routine. Do I have to post it? I am getting a BSOD in my PLOAD_IMAGE_NOTIFY_ROUTINE when I call KillProcess.
Here is my KillProcess function:
NTSTATUS KillProcess(HANDLE ProcessId)
{
PEPROCESS Process;
HANDLE newProcessHandle = NULL;
NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &Process);
do
{
if (!NT_SUCCESS(status))
{
#ifdef DEBUGPRINT
DbgPrint("Process with id %d does not exist\n", ProcessId);
#endif
break;
}
if (NT_SUCCESS(status = ObOpenObjectByPointer(
Process,
OBJ_KERNEL_HANDLE,
NULL,
PROCESS_TERMINATE,
*PsProcessType,
KernelMode,
&newProcessHandle
)))
{
if (newProcessHandle != NULL)
{
status = ZwTerminateProcess(newProcessHandle, 0);
ZwClose(newProcessHandle);
}
else
{
ObDereferenceObject(Process);
break;
}
if (NT_SUCCESS(status))
{
#ifdef DEBUGPRINT
DbgPrint("Successfully killed process with id %d\n", ProcessId);
#endif
}
else
{
#ifdef DEBUGPRINT
DbgPrint("Failed to kill process with id %d\n", ProcessId);
#endif
}
}
else
{
#ifdef DEBUGPRINT
DbgPrint("Failed to open process with id %d\n", ProcessId);
#endif
}
ObDereferenceObject(Process);
} while (FALSE);
return status;
}
The documentation for PsSetLoadImageNotifyRoutine says:
When the main executable image for a newly created process is loaded, the load-image notify routine runs in the context of the new process.
(It also seems likely that when a DLL is loaded, the call is made in the context of the process loading the DLL.)
So from the sounds of it, you are terminating the process whose context you are running in. What's more, you're doing it at a particularly vulnerable point, during a callback for an image load operation. It is not surprising that this causes trouble.
The documentation for ZwTerminateProcess implies that a driver can terminate the current process, provided that it ensures that resources have been freed from the kernel stack, but I don't think that applies in this situation. (Also, I don't know how you'd go about doing that.)
It might instead be possible to suspend the process, and terminate it later from a system thread.
The problem is I was trying to terminate the process in its own context which lead to a BSOD.
Solution:
Create a global variable holding the pid
Set the global variable
In a system thread, check if the global variable has changed
terminate the process
Related
I have a program that uses fork() to create a child process. I have seen various examples that use wait() to wait for the child process to end before closing, but I am wondering what I can do to simply check if the file process is still running.
I basically have an infinite loop and I want to do something like:
if(child process has ended) break;
How could I go about doing this?
Use waitpid() with the WNOHANG option.
int status;
pid_t result = waitpid(ChildPID, &status, WNOHANG);
if (result == 0) {
// Child still alive
} else if (result == -1) {
// Error
} else {
// Child exited
}
You don't need to wait for a child until you get the SIGCHLD signal. If you've gotten that signal, you can call wait and see if it's the child process you're looking for. If you haven't gotten the signal, the child is still running.
Obviously, if you need to do nothing unitl the child finishes, just call wait.
EDIT: If you just want to know if the child process stopped running, then the other answers are probably better. Mine is more to do with synchronizing when a process could do several computations, without necessarily terminating.
If you have some object representing the child computation, add a method such as bool isFinished() which would return true if the child has finished. Have a private bool member in the object that represents whether the operation has finished. Finally, have another method private setFinished(bool) on the same object that your child process calls when it finishes its computation.
Now the most important thing is mutex locks. Make sure you have a per-object mutex that you lock every time you try to access any members, including inside the bool isFinished() and setFinished(bool) methods.
EDIT2: (some OO clarifications)
Since I was asked to explain how this could be done with OO, I'll give a few suggestions, although it heavily depends on the overall problem, so take this with a mound of salt. Having most of the program written in C style, with one object floating around is inconsistent.
As a simple example you could have a class called ChildComputation
class ChildComputation {
public:
//constructor
ChildComputation(/*some params to differentiate each child's computation*/) :
// populate internal members here {
}
~ChildComputation();
public:
bool isFinished() {
m_isFinished; // no need to lock mutex here, since we are not modifying data
}
void doComputation() {
// put code here for your child to execute
this->setFinished(true);
}
private:
void setFinished(bool finished) {
m_mutex.lock();
m_isFinished = finished;
m_mutex.unlock();
}
private:
// class members
mutex m_mutexLock; // replace mutex with whatever mutex you are working with
bool m_isFinished;
// other stuff needed for computation
}
Now in your main program, where you fork:
ChildComputation* myChild = new ChildComputation(/*params*/);
ChildPID= fork();
if (ChildPID == 0) {
// will do the computation and automatically set its finish flag.
myChild->doComputation();
}
else {
while (1) { // your infinite loop in the parent
// ...
// check if child completed its computation
if (myChild->isFinished()) {
break;
}
}
// at the end, make sure the child is no runnning, and dispose of the object
// when you don't need it.
wait(ChildPID);
delete myChild;
}
Hope that makes sense.
To reiterate, what I have written above is an ugly amalgamation of C and C++ (not in terms of syntax, but style/design), and is just there to give you a glimpse of synchronization with OO, in your context.
I'm posting the same answer here i posted at as this question How to check if a process is running in C++? as this is basically a duplicate. Only difference is the use case of the function.
Use kill(pid, sig) but check for the errno status. If you're running as a different user and you have no access to the process it will fail with EPERM but the process is still alive. You should be checking for ESRCH which means No such process.
If you're running a child process kill will succeed until waitpid is called that forces the clean up of any defunct processes as well.
Here's a function that returns true whether the process is still running and handles cleans up defunct processes as well.
bool IsProcessAlive(int ProcessId)
{
// Wait for child process, this should clean up defunct processes
waitpid(ProcessId, nullptr, WNOHANG);
// kill failed let's see why..
if (kill(ProcessId, 0) == -1)
{
// First of all kill may fail with EPERM if we run as a different user and we have no access, so let's make sure the errno is ESRCH (Process not found!)
if (errno != ESRCH)
{
return true;
}
return false;
}
// If kill didn't fail the process is still running
return true;
}
I have read this and this post on stackoverflow, but no one of them give me what I want to do.
In my case, I want to create a Thread, launch it and let it running with no blocking stat as long as the main process runs. This thread has no communication, no synchronization with the main process, it do his job fully independent.
Consider this code:
#define DAY_PERIOD 86400 /* 3600*24 seconds */
int main() {
char wDir[255] = "/path/to/log/files";
compress_logfiles(wDir);
// do other things, this things let the main process runs all the time.
// just segmentation fault, stackoverflow, memory overwrite or
// somethings like that stop it.
return 0;
}
/* Create and launch thread */
void compress_logfiles(char *wDir)
{
pthread_t compressfiles_th;
if (pthread_create(&compressfiles_th, NULL, compress, wDir))
{
fprintf(stderr, "Error create compressfiles thread\n");
return;
}
if (pthread_join(compressfiles_th, NULL))
{
//fprintf(stderr, "Error joining thread\n");
return;
}
return;
}
void *compress(void *wDir)
{
while(1)
{
// Do job to compress files
// and sleep for one day
sleep(DAY_PERIOD); /* sleep one day*/
}
return NULL;
}
With ptheard_join in compress_logfiles function, the thread compresses all files successfully and never returns because it is in infinite while loop, so the main process still blocked all the time. If I remove ptheard_join from compress_logfiles function, the main process is not blocked because it don't wait thread returns, but the thread compresses one file and exit (there a lot of files, arround one haundred).
So, is there a way to let main process launch compressfiles_th thread and let it do his job without waiting it to finish or exit?
I found pthread_tryjoin_np and pthread_timedjoin_np in Linux Programmer's Manual, it seems that pthread_tryjoin_np do the job if I don't care of the returned value, it is good idea to use it?
Thank you.
Edit 1:
Please note that the main process is daemonized after call to compress_logfiles(wDir), perhaps the daemonization kill the main process and re-launch it is the problem?
Edit 2: the solution
Credit to dbush
Yes, fork causes the problem, and pthread_atfork() solves it. I made this change to run the compressfiles_th without blocking main process:
#define DAY_PERIOD 86400 /* 3600*24 seconds */
char wDir[255] = "/path/to/log/files"; // global now
// function added
void child_handler(){
compress_logfiles(wDir); // wDir is global variable now
}
int main()
{
pthread_atfork(NULL, NULL, child_handler);
// Daemonize the process.
becomeDaemon(BD_NO_CHDIR & BD_NO_CLOSE_FILES & BD_NO_REOPEN_STD_FDS & BD_NO_UMASK0 & BD_MAX_CLOSE);
// do other things, this things let the main process runs all the time.
// just segmentation fault, stackoverflow, memory overwrite or
// somethings like that stop it.
return 0;
}
child_handler() function is called after fork. pthread_atfork
When you fork a new process, only the calling thread is duplicated, not all threads.
If you wish to daemonize, you need to fork first, then create your threads.
From the man page for fork:
The child process is created with a single thread--the one that
called fork(). The entire virtual address space of the parent is
replicated in the child, including the states of mutexes, condition
variables, and other pthreads objects; the use of pthread_atfork(3)
may be helpful for dealing with problems that this can cause.
So far I've worked with processes and threads only on Linux platform.
Now I tried to move on Windows. And I got immediately stopped on very simple program.
Can you tell me why my program doesn't write anything if I remove the line with getch?
I want my thread to finish without me pressing anything.
Thank you in advance
#include <windows.h>
#include <stdio.h>
DWORD WINAPI ThreadFunc()
{
printf("lets print something");
return 0;
}
VOID main( VOID )
{
DWORD dwThreadId;
HANDLE hThread;
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
ThreadFunc, // thread function
NULL, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
// Check the return value for success.
if (hThread == NULL)
{
printf( "CreateThread failed (%d)\n", GetLastError() );
}
else
{
_getch();
CloseHandle( hThread );
}
}
If your box is relatively idle, the OS is quilte likely to signal the thread creation request to another core, so allowing the 'main' thread, (the one created by the process loader), to run on quickly. By the time your new thread gets round to calling the OS with the printf call, the main thread has already returned, the state of all threads for that process has been set to 'never run again' and a termination request queued up for it on its inter-processor core driver. The new thread is exterminated there and then and the now-redundant termination request discarded.
I'm having a problem in the combined use of execl() and pthread.
My idea is quite simple: write a daemon that in certain situation starts an external process (a separate executable with respect to the daemon itself) and wait for the return value of that process. Moreover I want to have the possibility to start multiple instances of the same process at the same time.
The part of my code to handle multiple threads:
...
for (c_thread=0,i=0;i<N;i++)
{
/* Start actions before start threads */
for (j=c_thread;j<c_thread+config.max_threads;j++)
Before_Process(act[act_index[j]].measID);
/* Now create threads */
for (c=0,j=c_thread;j<c_thread+config.max_threads;j++)
{
Print_Log(LOG_DEBUG,"Create tread n. %d, measurementID=%s",c,act[act_index[j]].measID);
if ((ret=pthread_create(&pth[c],NULL,Start_Process_Thread,(void *) &act[act_index[j]].measID)))
{
Print_Log(LOG_ERR,"Error in creating thread (errorcode: %d)",ret);
exit(EXIT_FAILURE);
}
c++;
}
/* Joint threads */
for (j=0;j<config.max_threads;j++)
{
if ((ret=pthread_join(pth[j], (void**) &r_value[j])))
{
Print_Log(LOG_ERR,"Error in joint thread (errorcode: %d)",ret);
exit(EXIT_FAILURE);
}
}
/* Perform actions after the thread */
for (j=0;j<config.max_threads;j++)
{
status=*(int*) r_value[j];
Print_Log(LOG_DEBUG,"Joint tread n. %d. Return value=%d",j,status);
After_Process(act[act_index[c_thread+j]].measID,status);
}
c_thread += config.max_threads;
}
...
And the function Start_Process_Thread:
void *Start_Process_Thread(void *arg)
{
int *ret;
char *measID;
measID=(char*)arg;
if (!(ret=malloc(sizeof(int))))
{
Print_Log(LOG_ERR, "allocation memory failed, code=%d (%s)",
errno, strerror(errno) );
exit(EXIT_FAILURE);
}
*ret=Start_Process(measID);
pthread_exit(ret);
}
int Start_Process(char *measID)
{
...
pipe(pfd);
pid=fork();
if (!pid)
{
signal(SIGALRM,Timeout);
alarm(config.timeout_process);
flag=0;
/*
Start the Process.
*/
ret=execl(config.pre_processor,buff_list[TokCount-1],config.db_name,measID,(char *) 0);
if (ret==-1)
{
alarm(0);
flag=1;
Print_Log(LOG_ERR,"Cannot run script %s, code=%d (%s)",config.process, errno, strerror(errno));
}
alarm(0);
close(1);
close(pfd[0]);
dup2(pfd[1],1);
write(1,&flag,sizeof(int));
}
else
{
wait(&status);
close(pfd[1]);
read(pfd[0],&flag,sizeof(int));
close(pfd[0]);
if (!flag)
{
if (WIFEXITED(status))
{
if (!(return_value=WEXITSTATUS(status)))
{
/*
Process gives no errors.
*/
Print_Log(LOG_INFO, "Processing of measurementID=%s ended succesfully!",measID);
}
else
{
/*
Process gives errors.
*/
Print_Log(LOG_WARNING,"Processor failed for measurementID=%s, code=%d",measID, return_value);
}
}
else
{
/*
Timeout for Process
*/
Print_Log( LOG_WARNING,"Timeout occurred in processing measurementID=%s",measID);
return_value=255;
}
}
}
}
The above code works fine from technical point of view but I have a problem somewhere in handling the return values of the different instances of the called external process. In particular it happens that the return value associated to a certain instance is attributed to a different one randomly.
For example suppose 4 different instances of the external process are called with the arguments meas1, meas2, meas3 and meas4 respectively and suppose that meas1, meas2 and meas3 are successfully processed and that for meas4 the process fails. In situation like that my code mix up the return vales giving success for meas1, meas3, and meas4 and failure for meas2 or success for meas1, meas2, meas4 and failure for meas3.
Any idea on why this can happens?
Any help is really welcome.
Thank you in advance for your attention.
When any thread in a process executes wait(), it gets the information about any of the process's dead children — not necessarily about the last child started by the thread that is doing the waiting.
You are going to need to think about:
Capturing the PID of the process that died (it is returned by wait(), but you ignore that).
Having a single thread designated as the 'disposer of corpses' (a thread that does nothing but wait() and record and report on deaths in the family of child processes).
A data structure that allows the threads that start processes to record that they are interested in the status of the child when it dies. Presumably, the child should wait on a suitable condition once a child starts so that it is not consuming CPU time doing nothing useful.
The 'disposer of corpses' thread handles notifications of the appropriate other thread whenever it collects a corpse.
Worry about timeouts on the processes, and killing children who run wild for too long.
It's a morbid business at times...
I'm programming in C using win32 api.
My program starts at void main , I do some action that create mutex with specific name
and then launching waitForSingleObject function on it with INFINITE time parameter.
Then I'm launching an EXE process by createProcess function.
The EXE process has a similar code that is now doing createMutex with the same name I did before with the parent process.
As I understand I should get a handle to the same mutex I created in the parent program.. because it has the same name.
So after that, the EXE code is also doing again WaitForSingleObject on the mutex handle
with same parameters.
I have expected this to stop and wait now but it continued as it was signaled somehow, but there is no way I did a signal anywhere at this stage.
I tried to replace the INFINITE parameter with 0 and to see if I get WAIT_TIMEOUT but this didn't work also.
Why my mutex don't work?
Thanks
relevant code added: (I tried to put only things that are relevant)
* please note the the EXE file Process1 contains a code that does openfileInDirectory with the same file name I did in void main and for write.
** My mutex to follow is that is called writeMutex. FileSystemMutex is another one that has nothing to do with my current problem.
// Global variables definition from library header
void* viewVec;
HANDLE fileHandle;
int directoryLastBlockIndex;
FilesInProcessUse processFiles;
HANDLE fileSystemMutex;
HANDLE filesAccessSemaphore;
void main()
{
FileDescriptor* fd, *fd2;
int message,message2,message3;
int processId = GetCurrentProcessId();
char* input= NULL;
/* print out our process ID */
printf("Process %d reporting for duty\n",processId);
fileSystemMutex = CreateMutex(NULL,FALSE,FILE_SYSTEM_MUTEX_NAME);
printf("Process %d: After creating fileSystem mutex\n",processId);
filesAccessSemaphore = CreateSemaphore(NULL,MAX_ACCESSORS_FOR_ALL_FILES,MAX_ACCESSORS_FOR_ALL_FILES,FILE_SYSTEM_SEMAPHORE_NAME);
printf("Process %d: After creating filesAccessSemaphore\n",processId);
initfs("C",NUM_OF_BLOCKS_IN_DISK,NUM_OF_BLOCKS_IN_DISK);
viewVec = attachfs("C"); // Saving the address of the vector in global pointer.
if(viewVec!=NULL)
{
printf("Process %d: After AttachFS which succeded\n",processId);
fd = (FileDescriptor*) createFileInDirectory("FileX",2,&message);
if (fd!=NULL)
{
printf("Process %d:successfuly created the file: FileX in Drive C\n",processId);
}
else
{
printErrMessage(message);
}
}
else
{
printf("Process %d: After AttachFS, which failed\n",processId);
}
fd = (FileDescriptor*) openFileInDirectory("FileX",READ_PERMISSION,&message);
if(fd!=NULL)
{
printf("Process %d: opened FileXfile for read succefully",processId);
}
else
{
printf("Process %d:",processId);
printErrMessage(message);
}
closeFileInDirectory(fd);
fd = (FileDescriptor*) openFileInDirectory("FileX",WRITE_PERMISSION,&message);
if(fd!=NULL)
{
printf("Process %d: opened FileXfile for write succefully",processId);
}
else
{
printf("Process %d:",processId);
printErrMessage(message);
}
fd2 = (FileDescriptor*) openFileInDirectory("FileX",WRITE_PERMISSION,&message);
if(fd!=NULL)
{
printf("Process %d: opened FileX file for write succefully",processId);
}
else
{
printf("Process %d:",processId);
printErrMessage(message);
}
}
}
void* openFileInDirectory(char* fileName, int ReadWriteFlag, int* out_ErrMessage)
{
SystemInfoSection* sysInfo = readSystemInformationFromBeginingOfVector((char*)viewVec);
DirectoryEntry* fileEntryInDirOffset;
FileDescriptor* openfileDescriptor = NULL;
int fileIndexInOpenFiles = 0;
int writeRV;
//Mark that another file is being processed
WaitForSingleObject(filesAccessSemaphore,INFINITE);
//Check if the file exists else return error
if(isFileAlreadyExisting(fileName, sysInfo->directoryStartBlockIndex, &fileEntryInDirOffset))
{
fileIndexInOpenFiles = getFileIndexInOpenFileDirectory(fileName);
processFiles.allFilesVector[fileIndexInOpenFiles].accessSemaphore = CreateSemaphore(NULL,MAX_FILE_ACCESSORS,MAX_FILE_ACCESSORS,fileName);
WaitForSingleObject(processFiles.allFilesVector[fileIndexInOpenFiles].accessSemaphore,INFINITE);
if (ReadWriteFlag == WRITE_PERMISSION)
{
char writeMutexName[15];
strcpy(writeMutexName, WRITE_MUTEX_PREFIX);
strcat(writeMutexName, fileName);
processFiles.allFilesVector[fileIndexInOpenFiles].writeMutex = CreateMutex(NULL,FALSE,writeMutexName);
WaitForSingleObject(processFiles.allFilesVector[fileIndexInOpenFiles].writeMutex,INFINITE);
//writeRV = WaitForSingleObject(processFiles.allFilesVector[fileIndexInOpenFiles].writeMutex,MAX_WAIT_TIMEOUT_IN_FS);
//if(writeRV == WAIT_TIMEOUT)
//{
// ReleaseSemaphore(processFiles.allFilesVector[fileIndexInOpenFiles].accessSemaphore,1,NULL);
// //return error indicating that another process is already writing to the file AND RETURN FROM THE FUNCTION
// *out_ErrMessage = ERR_FILE_IS_ALREADY_OPEN_TO_A_WRITE_BY_SOME_PROCESS;
// return openfileDescriptor;
//}
}
processFiles.FDInProcessUseVector[fileIndexInOpenFiles].fileDirectoryEntry = fileEntryInDirOffset;
processFiles.FDInProcessUseVector[fileIndexInOpenFiles].readWriteFlag = ReadWriteFlag;
openfileDescriptor = &(processFiles.FDInProcessUseVector[fileIndexInOpenFiles]);
processFiles.numOfFilesInUse++;
}
else
{
openfileDescriptor = NULL;
*out_ErrMessage = ERR_FILE_NOT_FOUND;
}
free(sysInfo);
return openfileDescriptor;
}
You can use CreateMutex function to create named global mutex.
Logic of using global mutex is usually following:
You try to create mutex by using CreateMutex. Note that "If the mutex is a named mutex and the object existed before this function call, the return value is a handle to the existing object".
You lock (get ownership) by using WaitForSingleObject function
You unlock (release ownership) by using ReleaseMutex function
You CloseHandle returned by CreateMutex function.
Here is good example in C: Using Mutex Objects
There are few problems in your code:
You don't release ownership of writeMutex, which is probably the main reason why this code can't work.
You don't check the return value of a single call. The only return value that you check is the one returned from your function. Check documentation of these functions so that you can handle possible error states properly.
You don't CloseHandle returned by CreateMutex function. Neither handle of fileSystemMutex nor handle of writeMutex.
You create fileSystemMutex, but then you never use it. This mutex has no sense there.