Using Job Objects to manipulate processes

 

This is beginner post related to using Job objects in windows. If you’re a core native programmer, you might have a chance to deal with Job objects. One of the best realworld application managing with job objects are Visual Studio itself. The IDE compiles and links your source code by using “CL.exe” compiler and “Link.exe”.The IDE has sole control over the behavior and life time of the processes it deals with. How we can do that? To help with such scenarios, Windows supports Jobs objects. It allows grouping the application and restricting its behavior in various conditions. Read more about Job objects from MSDN. Another best example is Google Chrome Browser which manages its tabs as process. If you check with Process Explorer, you can see the chrome tabs as process and from its properties; you will get the information about the job.

What are the basic steps for dealing with Job objects?

  1. You’ve to create the Job object using CreateJobObject API.
  2. Define the behavior of the job
  3. Create or open the process you need to group.
  4. Assign the process to job, using “Job Objects”
  5. Manage the notifications of from the assigned processes or jobs

Creating Job Object

You can create a new job object as follows.

[sourcecode language='cpp']
m_hJob = CreateJobObject( NULL, _T(“NotepadJobs”)); // Create Job object
if ( !m_hJob)
{
MessageBox( _T(“Failed to create Job Object”),_T(“Job Error”),MB_OK|MB_ICONERROR);
return;
}

JOBOBJECT_BASIC_LIMIT_INFORMATION bli = { 0 };
bli.PriorityClass = HIGH_PRIORITY_CLASS;
bli.PerJobUserTimeLimit.QuadPart = 1000;
SetInformationJobObject( m_hJob, JobObjectBasicLimitInformation, &bli, sizeof(bli));
[/sourcecode]

The next you can provide as many supported restrictions to your job. Get a complete list of the restrictions and its usage from MSDN.

Create new process and assign to job object

You can simply using create process to create the new process and get it’s handle to attach with the job object.

[sourcecode language='cpp']
STARTUPINFO st = { sizeof(st) };

STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
TCHAR buff[] = _T(“C:\\Windows\\Notepad.exe”);
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
buff, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent’s environment block
NULL, // Use parent’s starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
return;
}

[/sourcecode]

The above code creates a notepad application. You can create your own application to attach with job object. The next thing you need to do is, assign the process to job object. Using AssignProcessToJobObject

[sourcecode language='cpp']
// Close process and thread handles.
AssignProcessToJobObject( m_hJob, pi.hProcess );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
[/sourcecode]

Now your process will be appeared on the screen. Now you want to track the main activities like, adding a new process, exiting new process etc.. of your job object.

Add thread to monitor the notifications from the Jobs

After initializing simply create a thread to monitor the activities of your job object.

First you have to create a new thread for monitoring purpose using CreateThread API as follows.

CreateThread( 0, 0, ThreadFxn,m_hJob,0,0);

To implement the Job notifications, first we’ve to create an IO completion port for detecting changes. Since IO completion port not coming in the scope of this article, I’m planning it for some other time.

You can use CreateIoCompletionPort API to implement an IO completion port

[sourcecode language='cpp']
HANDLE hiocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,1,0 );
[/sourcecode]

Set the newly created IO completion port to the job object

[sourcecode language='cpp']
// Set the IO completion port handle to the job for notifications

JOBOBJECT_ASSOCIATE_COMPLETION_PORT
iop;
iop.CompletionKey = (PVOID)1;
iop.CompletionPort = hiocp;
SetInformationJobObject( hJob, JobObjectAssociateCompletionPortInformation,
&iop,sizeof(iop));
[/sourcecode]

Wait for IO completion Port

[sourcecode language='cpp']
while( WAIT_OBJECT_0 == WaitForSingleObject(hiocp,INFINITE))
[/sourcecode]

Once the IOCP signaled, then get the status using GetQueuedCompletionStatus API

[sourcecode language='cpp']
if(GetQueuedCompletionStatus( hiocp,&dwBytes,&completionkey,&ove,INFINITE))
[/sourcecode]

Check which was the message of interest

[sourcecode language='cpp']
if (dwBytes == JOB_OBJECT_MSG_NEW_PROCESS)
AfxMessageBox( _T( “New process”));
else if( dwBytes == JOB_OBJECT_MSG_EXIT_PROCESS)
AfxMessageBox( _T( “Exit process”));
else if(dwBytes == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO)
AfxMessageBox(_T( “No further processes”));
[/sourcecode]

You can get the complete list of options from MSDN. The LPOVERLAPPED parameter will be holding data according to the message got signaled.

The entire monitor thread function may appear as follows

[sourcecode language='cpp']

DWORD WINAPI ThreadFxn(LPVOID lpVoid)
{
// Get the pointer to job object
HANDLE hJob = (HANDLE)lpVoid;
// Create IO completion port (no files are attached)
HANDLE hiocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,1,0 );

// Set the IO completion port handle to the job for notifications
JOBOBJECT_ASSOCIATE_COMPLETION_PORT iop;
iop.CompletionKey = (PVOID)1;
iop.CompletionPort = hiocp;
SetInformationJobObject( hJob, JobObjectAssociateCompletionPortInformation,
&iop,sizeof(iop));

// Wait for events
while( WAIT_OBJECT_0 == WaitForSingleObject(hiocp,INFINITE))
{
DWORD dwBytes;
ULONG_PTR completionkey;
LPOVERLAPPED ove;
if(GetQueuedCompletionStatus( hiocp,&dwBytes,&completionkey,&ove,INFINITE))
{
if (dwBytes == JOB_OBJECT_MSG_NEW_PROCESS) // Check *ove for additional information with the notification
{
AfxMessageBox( _T( “New process”));
}
else if( dwBytes == JOB_OBJECT_MSG_EXIT_PROCESS)
{
AfxMessageBox( _T( “Exit process”));

}
else if(dwBytes == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO)
{
AfxMessageBox(_T( “No further processes”));
}
}
else
{
AfxMessageBox( _T(“Failed”));
}
}
return 0;
}
[/sourcecode]

This is the simple way to manage the Job objects with notification. If you want to give further inputs, give feedback through comments.

 

Who's she, in the standard test image?

 

If you notice most popular image processing applications, we could see a beautiful and sexy face of a girl as the standard test image. I was thinking, why most of the applications using the same image. I finally I managed to find her name from a sample file. It was Lena (or Lenna). Googling on her name returned a proper link to Wikipedia.

The image is originally cropped (:D) from Playboy Magazine centerfold picture. Swedish model Lena Söderberg paused naked for the 1972 November issue of Playboy magazine. It’s one of the most widely used images for testing image processing algorithms such as compression, denoising etc…

According to David C. Munson, editor-in-chief, January 1996 IEEE Transactions on Image Processing the wide popularity of image is because of two reasons.

First, the image contains a nice mixture of detail, flat regions, shading, and texture that do a good job of testing various image processing algorithms. It is a good test image! Second, the Lena image is a picture of an attractive woman. It is not surprising that the (mostly male) image processing research community gravitated toward an image that they found attractive    

Wikipedia also cited the controversy regarding this particular image.

The use of the image has produced some controversy, with some people concerned about Playboy magazine as the source of the image, and with the image being copyrighted.

When the IS&T wanted to invite Lena to their meeting,[5]

“Playboy helped track down the Swedish native in Stockholm, where she helps handicapped people work on (non-networked) computers. Although Playboy is notorious for cracking down on illegal uses of its images, it has decided to overlook the widespread distribution of this particular centerfold.

Says Eileen Kent, VP of new media at Playboy: “We decided we should exploit this, because it is a phenomenon.”"

Coincidentally, Playboy states the issue was its best-selling ever, having sold 7,161,561 copies as of May 2006.

OK that’s the story behind Lena!!!