I am learning semaphores, and wanted to try out semaphore IPC on a shared memory program I have implemented before. (The program involves sharing the Shared Memory between parent and child process: Reading and writing it etc). When I use a variable and increment it in Parent and decrement it in child, due to Race condition I get unexpected output. So i wanted to synchronize the two using Semaphore. But I needed a starting point, a template to begin with.
I have done the previous shared memory example using such template (initializing,attaching,detaching etc) I found else where. So if anyone can suggest some steps...
What I am trying:
struct shmarea // My shared Memory
{
` unsigned long count;
};
struct shmarea *shma;
main()
{
id = shmget(KEY1,4096,IPC_CREAT|0600);
shma = shmat(id,0,0);
shma->count = 0;
ret = fork();
if(ret>0)
{
printf("in parent .. ppid is %lu ...and pid is %lu\n",getppid(),getpid());
sleep(5);
while(j++ < 2147483645){ // The large loop is to See the processes in top command
while(i++ < 2147483645) shma->count++;
}
}
if(ret==0)
{
printf("in child .. ppid is %lu ...and pid is %lu\n",getppid(),getpid());
while(j++ < 2147483645){
while(i++ < 2147483645) shma->count--;
}
exit(0);
}
if(ret>0)
{
//Clean up
}
}
I did look for Semaphore creation examples..But mostly I am stuck with use of semaphore sets..How to map it with binary semaphore...because in this simple program i just need to have two values 0 and 1.
Related
I got a question while I'm doing for ray-tracing stuff.
I have created multiple threads to split whole image to be processed and let it process its allocated task. Threads work well as it is intended. I would like to monitor the work progress in real-time.
To resolve this problem, I have created one more thread to monitor current state.
Here is the monitoring pseudo-code:
/* Global var */
int cnt = 0; // count the number of row processed
void* render_disp(void* arg){ // thread for monitoring current render-processing
/* monitoring global variable and calculate percentage to display */
double result = 100.*cnt/(h-1);
fprintf(stderr,"\r3.2%f%% of image is processed!", result);
}
void* process(void* arg){ // multiple threads work here
// Rendering process
for(........)
pthread_mutex_lock(&lock);
cnt++;
pthread_mutex_unlock(&lock);
for(........)
}
I wrote the code for initialization of pthread and mutex in main() function.
Basically, I think this monitoring thread should display current state but this thread seems to be called only once and quit.
How do I change this code to this thread function to be called until the whole rendering is finished?
I've found a Torjan on Linux system, it uses a method called "fast fork", like the code below
while(1)
{
count += 1;
pid_t pid = fork();
if (pid < 0)
{
printf("there is something wrong\n");
}
if (pid > 0) // father process
{
/* every 0x1000 times fork run the evil code once */
if (count & 0xfff)
{
exit(0);
}
/* stop the program if the job isn't done in XXs */
alarm(XX);
// evil code
}
}
It's really effective and you can't find it via ps aux, is there anyway to find the process and kill it without reboot?
P.S. The code runs as a normal user (not root) and I don't have root access either.
If the process name doesn't change after each fork, you can use a method called "fast kill", like this
$ while true; do killall -9 process_name; done
(but how to get the process name if the origin file has been removed? sorry I don't have enough reputation to add a comment)
I have come across a problem with my application and the spawnProcess.
If the main application for some reason dies/is killed then the spawned processes seem to live on and I can't reach them unless I use terminal to kill them via their PIDs. My goal is if the main application dies then the spawned processes should be killed also, somehow.
My code is like this
auto appPid = spawnProcess("path/to/process");
scope(exit){ auto exitcode = wait(appPid);
stderr.writeln(...);}
And if I use the same approach when the main process dies, using wait(thisProcessID) I get an error. "No overload matches". Any ideas how to solve this problem?
Here's some code that will do it on Linux. It doesn't have all the features of the stdlib's spawnProcess, it just shows the bare basics, but expanding it from here isn't hard if you need more.
import core.sys.posix.unistd;
version(linux) {
// this function is Linux-specific
import core.stdc.config;
import core.sys.posix.signal;
// we can tell the kernel to send our child process a signal
// when the parent dies...
extern(C) int prctl(int, c_ulong, c_ulong, c_ulong, c_ulong);
// the constant I pulled out of the C headers
enum PR_SET_PDEATHSIG = 1;
}
pid_t mySpawnProcess(string process) {
if(auto pid = fork()) {
// this branch is the parent, it can return the child pid
// you can:
// import core.sys.posix.sys.wait;
// waitpid(this_ret_value, &status, 0);
// if you want the parent to wait for the child to die
return pid;
} else {
// child
// first, tell it to terminate when the parent dies
prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
// then, exec our process
char*[2] args;
char[255] buffer;
// gotta copy the string into another buffer
// so we zero terminate it and have a C style char**...
buffer[0 .. process.length] = process[];
buffer[process.length] = 0;
args[0] = buffer.ptr;
// then call exec to run the new program
execve(args[0], args.ptr, null);
assert(0); // never reached
}
}
void main() {
mySpawnProcess("/usr/bin/cat");
// parent process sleeps for one second, then exits
usleep(1_000_000);
}
So the lower level functions need to be used, but Linux does have a function that does what you need.
Of course, since it sends a signal, your child might want to handle that to close more gracefully than the default termination, but try this program and run ps while it sleeps to see cat running, then notice the cat dies when the parent exits.
So my program spawns a number of child processes in response to certain events, and I'm doing something ike this to keep track and kill them upon program exit (Perl syntax):
my %children = ();
# this will be called upon exit
sub kill_children {
kill 'INT' => keys %children;
exit;
}
# main code
while(1) {
...
my $child = fork();
if ($child > 0) {
$children{$child} = 1;
} elsif ($child == 0) {
# do child work ...
exit();
} else {
# handle the error
}
}
So the idea is as above. However, there's a blatant race condition there, in that a given child can start and terminate before the father has a chance to run and record its pid in the %children hash. So the father may end up thinking that a given pid belongs to an active child, even if this child has terminated.
Is there a way to do what I'm trying to accomplish in a safe way?
Edit: To better keep track of children, the code can be extended as follows (which however also suffer of the exact same race condition, so that's why I didn't write it fully in the first place):
my %children = ();
sub reap {
my $child;
while (($child = waitpid(-1, WNOHANG)) > 0) {
#print "collecting dead child $child\n";
delete $children{$child};
}
}
$SIG{CHLD} = \&reap;
# this will be called upon exit
sub kill_children {
local $SIG{CHLD} = 'IGNORE';
kill 'INT' => keys %children;
exit;
}
# main code
while(1) {
...
my $child = fork();
if ($child > 0) {
$children{$child} = 1;
} elsif ($child == 0) {
# do child work ...
exit();
} else {
# handle the error
}
}
Even in this case, the contents of %children may not reflect the actual active children.
Edit 2: I found this question, which is exactly about the same problem. I like the solution suggested in there.
On UNIX it's not a race condition. This is the standard way to handle fork(). When the child process exits, its status is changed to "terminated"; it becomes a zombie. It still has an entry in the process table until the parent process calls one of the wait functions. Only after that is the dead process really removed.
Even if the parent sets itself up to ignore SIGCHLD, it still wouldn't qualify as a race condition; the parent would just have a PID that's not valid anymore. In that case, wait() would return ECHILD. But setting SIGCHLD would free up a child's PID, possibly leading to the parent trying to kill a process that is not a child.
On Windows, which doesn't have a fork call, it is emulated by creating a thread in the perl process. See perlfork. I'm not knowlegable enough about Windows to opinionate about if that could cause a race condition, but I suspect not.
I have this piece of code in a program function.
And there is a test script which hits this code path.
script goes through this function multiple times (~1000).
fork() call is successful as I can see child pid from parent block syslog but I don't see anything from child block.
This does NOT happen always. Happens only once in a hundred attempts.
Any idea what can be the general reasons for this to happen.
And what should I look for to get more information about the failure.
int i;
if ((i = fork()) < 0) {
syslog(LOG_NOTICE, "(%s): fork failed!\n", __func__);
}
if (i) {
syslog(LOG_NOTICE, "(%s): fork Parent: id: %d\n", __func__, i);
} else {
syslog(LOG_NOTICE, "(%s): fork child\n", __func__);
/* Do something */
}
Output:
telnetd[24600]: (startslave): fork Parent: id: 24601
<Thats it, no log after this!!>
To be exact, this is a part of freeBSD telnetd startslave() code, and script is just trying to login using telnet and logout for 1000 times and it fails sometimes. Failure is guaranteed, it can happen may be after 100 attempts or may be after 700 attempts.