Reputation: 889
I do not know, if this is ok, but it compiles:
typedef struct
{
int fd;
char *str;
int c;
} ARG;
void *ww(void *arg){
ARG *a = (ARG *)arg;
write(a->fd,a->str,a->c);
return NULL;
}
int main (void) {
int fd = open("./smf", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
int ch = fork();
if (ch==0){
ARG *arg; pthread_t p1;
arg->fd = fd;
arg->str = malloc(6);
strcpy(arg->str, "child");
arg->c = 6;
pthread_create( &p1, NULL, ww, arg);
} else {
write(fd, "parent\0", 7);
wait(NULL);
}
return 0;
}
I am wait()int in parent, but I do not know if I should also pthread_join
to merge threads or it is implicitly by wait()
. However is it even safe to write to the same file in two threads? I run few times and sometimes output was 1) parentchild
but sometimes only 2) parent
, no other cases - I do not know why child did not write as well when parent wait()s for it. Can someone please explain why these outputs?
Upvotes: 2
Views: 307
Reputation: 181869
I do not know, if this is ok, but it compiles:
Without even any warnings? Really? I suppose the code you are compiling must include all the needed headers (else you should have loads of warnings), but if your compiler cannot be persuaded to spot
buggy.c:30:15: warning: ‘arg’ may be used uninitialized in this function [-Wmaybe-uninitialized] arg->fd = fd; ^
then it's not worth its salt. Indeed, variable arg
is used uninitialized, and your program therefore exhibits undefined behavior.
But even if you fix that, after which the program can be made to compile without warnings, it still is not ok.
I am wait()int in parent, but I do not know if I should also
pthread_join
to merge threads or it is implicitly bywait()
.
The parent process is calling wait()
. This waits for a child process to terminate, if there are any. Period. It has no implications for the behavior of the child prior to its termination.
Moreover, in a pthreads program, the main thread is special: when it terminates, the whole program terminates, including all other threads. Your child process therefore suffers from a race condition: the main thread terminates immediately after creating a second thread, without ensuring that the other thread terminates first, so it is undefined what, if any, of the behavior of the second thread is actually performed. To avoid this issue, yes, in the child process, the main thread should join the other one before itself terminating.
However is it even safe to write to the same file in two threads?
It depends -- both on the circumstances and on what you mean by "safe". POSIX requires the write()
function to be thread-safe, but that does not mean that multiple threads or processes writing to the same file cannot still interfere with each other by overwriting each other's output.
Yours is a somewhat special case, however, in that parent and child are writing via the same open file description in the kernel, the child having inherited an association with that from its parent. According to POSIX, then, you should see both processes' output (if any; see above) in the file. POSIX provides no way to predict the order in which those outputs will appear, however.
I run few times and sometimes output was 1)
parentchild
but sometimes only 2)parent
, no other cases - I do not know why child did not write as well when parent wait()s for it. Can someone please explain why these outputs?
The child process can terminate before its second thread performs its write. In this case you will see only the parent's output, not the child's.
Upvotes: 2
Reputation: 73379
You need to call pthread_join() in the child process to avoid potential race conditions during the child process’s exit sequence (for example the child process can otherwise exit before its thread gets a chance to write to the file). Calling pthread_join() in the parent process won’t help,
As for the file, having both processes write to it is safe in the sense that it won’t cause a crash, but the order in which the data is written to the file will be indeterminate since the two processes are executing concurrently.
Upvotes: 3