So I've got a problem with my code and it's driving me nuts since I can't seem to figure out what's causing this. Basically, I'm trying to write to a file that I have open, using multiple child processes with fork(). Before I start forking, I can write to it just fine, but once I fork and THEN do an if statement to see if it's the child process, it won't write.
Basically, what I have is this:
FILE *output = NULL;
output = fopen(...); // Done successfully
fprintf(output, "This writes okay\n");
// Fork n processes
for (i = 0; i <= n; n++)
{
pid[i] = fork();
fprintf(output, "We can still write\n");
if (pid[i] == 0) // Child process
{
fprintf(output, "This won't write to output\n");
printf("I can still write and calculate stuff otherwise\n");
...
}
}
Can anyone figure out why it's not able to write after checking to see if it's a child process? There's definitely no error with forking from what I've seen.
Opening a file descriptor and using it in more than one process (for example in both a parent and child process) is a race condition and will most likely cause problems and unpredictable behavior.
Related
I have a pretty complicated OpenCL app. It fires up 5 different contexts on 5 different GPUs, and executes the same kernel on all of them, splitting up the work into 1024 "chunks" to be processed.
Each time a kernel finishes, a result is checked for, and it's given a new chunk. Sometimes, when running, as the app is starting (very rarely mid-run) it will immediately segfault on the GetEventInfo call.
This is done in a loop using callbacks and clGetEventInfo calls to ensure something is finished before moving on to the next step.
GDB output:
(gdb) back
#0 0x00007fdc686ab525 in clGetEventInfo () from /usr/lib/libOpenCL.so.1
#1 0x00000000004018c1 in ready (event=0x26a00000267) at gputest.c:165
#2 0x0000000000404b5a in main (argc=9, argv=0x7fffdfe3b268) at gputest.c:544
The ready function:
int ready(cl_event event) {
int rdy;
if(!event)
return 0;
clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &rdy, NULL);
if(rdy == CL_COMPLETE)
return 1;
return 0;
}
How the kernel is run, the event set, and checked. Some pseudocode inserted for brevity:
while(test if loop is complete) {
for(j = 0; j < GPUS; j++) {
if(gpu[j].waiting && loops < 9999) {
gpu[j].waiting = 0;
offset[j] = loops * 1024 * 1024;
loops++;
EC("kernel init", clEnqueueNDRangeKernel(queues[j], kernel_init[j], 1, &(offset[j]), &global_work_size, &work128, 0, NULL, &events[j]));
gpu[j].readsearch = events[j];
gpu[j].reading = 1;
}
}
for(j = 0; j < GPUS; j++) {
if(gpu[j].reading && ready(gpu[j].readsearch)) {
gpu[j].reading = 0;
gpu[j].waiting = 1;
// unrelated reporting other code here
}
}
}
Its pretty simple. There is more to the code, but it's unrelated. The ready/checking function is very simple. I even added debugging to the ready function to printf the event # to see what was happening when it crashed - nothing really. No pattern I could see.
What could be causing this?
Ugh. Found the problem. Since you cannot initialize values when you create/declare a struct, I was using some values uninitialized. I malloc'ed the gpu structs then just started using them. With if(gpu[x].reading &&...) being random data and completely uninitialized. So sometimes it was non-zero, which allowed the ready() function to fire off. Since the gpu[x].readsearch event was never set in the first place, clGetEventInfo bombed trying to use whatever was at the memory location.
This would be time number 482,847 that accidentally using uninitialized variables has burned me.
I've written a program that reads text from one file and copies it to a new file. Using a while loop and the ReadFile/Writefile functions, my program works...but my program won't stop running unless I force stop it. I'm guessing that I'm not closing my handles properly or that my while loop may be set up wrong. Once I force stop my program, the file is successfully copied over to the new location with a new name.
int n = 0;
while(n=ReadFile(hFileSource, buffer, 23, &dwBytesRead, NULL)){
WriteFile(hFileNew, buffer, dwBytesRead, &dwBytesWritten, NULL);
}
CloseHandle(hFileSource);
CloseHandle(hFileNew);
return 0;
You're not correctly testing for the end-of-file. ReadFile doesn't return failure for EOF, it returns success but with 0 bytes read. To correctly check for EOF:
while (ReadFile(hFileSource, buffer, 23, &dwBytesRead, NULL))
{
if (dwBytesRead == 0)
break;
// write data etc
}
Is there any reason you're only reading/writing 23 bytes at a time? This will be rather inefficient.
I've just recently learned about pipes and I would like to emulate the "|" gimmick provided by shells.
In the code below, the parent process spawns 2 child processes, after which they do their piping and get replaced by ls and grep. While that happens the parent process waits patiently. The problem is that the child processes never finish although they manage to send some data though the pipe and onto the screen.
There are other posts regarding pipes on SO, but I've never seen the setup in which the parent process launches 2 children. I've only seen the parent communicating with one child.
int p0[2];
pipe(p0); //creating pipe
if(fork() == 0) { //child 1
dup2(p0[0], STDIN_FILENO);
close(p0[0]); close(p0[1]);
execlp("grep","grep","a",NULL);
}
else { //parent
if(fork() == 0) { //child 2
dup2(p0[1], STDOUT_FILENO);
close(p0[0]); close(p0[1]);
execlp("ls","ls",NULL);
}
else { //parent
wait(NULL);
wait(NULL); //waiting for c1 and c2
close(p0[0]); close(p0[1]);
printf("parent exit\n");
}
}
My questions are: Why don't the child processes finish? Is fork-pipe structure sound or am I doing it completely wrong?
Close the pipe before starting to wait in the last section.
fork() is used to create a child process...and you see this call appear in the child process as well. I don't understand what it means when they say that 'calls to fork actually return twice'.
And what does this mean...
if (fork() == 0)
/* the child process's thread executes here*/
else
/*the parent process's thread executes here*/
Is the above code part of parent or child. Can you explain in plain English what's going on?
Also, why use a fork()? It says all processes in unix run by this system call? How do you fork() so other programs can run? Do you specify the name of the program?
It's a bit like this:
Process 1 Process 2
int main() {
...
int x = goo();
...
int y = fork();
// fork() returns... // ... but also here!
// here y = 123 // here y = 0
if (y) { if (y) {
// this happens // false
} else { } else {
// false // this happens
} }
int z = baz(); int z = baz();
... ...
return 0; return 0;
} }
When Process 2 comes to life, the program exists twice, and the second process starts with the return of fork(). Since the program is the same in both processes, the only way to distinguish which process you're in is by the return value of fork().
What the mean when they say it returns twice is that the call returns once in the parent process (which called it), and once in the child process (which didn't, although you could probably argue that the child inherited the act of calling fork from the parent just like it inherited so much else).
The code snippet takes advantage of the fact that get a different return value from fork depending on whether you're the parent process or the child process.
The child process gets zero and the parent process gets the non-zero process ID of the child.
You can also get back -1 if the fork fails for some reason, in which case the child won't be running. That's something you should probably check as well.
And, while fork is used to create new processes, it's the exec family of calls which load new programs into those processes: fork on its own cannot do that.
A good overview of the process can be found here.
I'm writing a fake shell, where I create a child process and then call execvp(). In the normal shell, when I enter an unknown command such as 'hello' it returns 'hello: Command not found.' However, when I pass hello into execvp(), it doesn't return any error by default and just continues running the rest of my program like nothing happened. What's the easiest way to find out if nothing was actually run? here's my code:
if(fork() == 0)
{
execvp(cmd, args);
}
else
{
int status = 0;
int corpse = wait(&status);
printf(Child %d exited with a status of %d\n", corpse, status);
}
I know that if corpse < 0, then it's an unknown command, but there are other conditions in my code not listed where I don't want to wait (such as if & is entered at the end of a command). Any suggestions?
All of the exec methods can return -1 if there was an error (errno is set appropriately). You aren't checking the result of execvp so if it fails, the rest of your program will continue executing. You could have something like this to prevent the rest of your program from executing:
if (execvp(cmd, args) == -1)
exit(EXIT_FAILURE);
You also want to check the result of fork() for <0.
You have two independent concerns.
1) is the return value of execvp. It shouldn't return. If it does there is a problem. Here's what I get execvp'ing a bad command. You don't want to wait if execvp fails. Always check the return values.
int res = execvp(argv[1], argv);
printf ("res is %i %s\n", res, strerror(errno));
// => res is -1 No such file or directory
2) The other concern is background processes and such. That's the job of a shell and you're going to need to figure out when your program should wait immediately and when you want to save the pid from fork and wait on it later.