xref: /haiku/src/tests/system/kernel/cow_bug113_test.cpp (revision f9eba888cacd8d30171db256c98aa88cebcf5b17)
1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/stat.h>
4 #include <unistd.h>
5 
6 #include <OS.h>
7 
8 const char* kInitialValue = "/dev/null";
9 const char* kChangedValue = "Argh!";
10 
11 int
main(int argc,const char * const * argv)12 main(int argc, const char* const* argv)
13 {
14 	thread_id parent = find_thread(NULL);
15 
16 	char* globalVar = NULL;
17 	area_id area = create_area("cow test", (void**)&globalVar,
18 		B_ANY_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
19 	if (area < 0) {
20 		printf("failed to create area\n");
21 		return 1;
22 	}
23 
24 	strcpy(globalVar, kInitialValue);
25 
26 	printf("[%ld] parent: before fork(): globalVar(%p): \"%s\"\n", parent,
27 		globalVar, globalVar);
28 
29 	pid_t child = fork();
30 	if (child == 0) {
31 		// child
32 		child = find_thread(NULL);
33 
34 		// let the kernel read access the page
35 		struct stat st;
36 		stat(globalVar, &st);
37 
38 		printf("[%ld] child: after kernel read: globalVar: \"%s\"\n",
39 			child, globalVar);
40 
41 		// write access the page from userland
42 		strcpy(globalVar, kChangedValue);
43 
44 		printf("[%ld] child: after change: globalVar: \"%s\"\n", child,
45 			globalVar);
46 
47 	} else {
48 		// parent
49 
50 		// wait for the child
51 		status_t exitVal;
52 		while (wait_for_thread(child, &exitVal) == B_INTERRUPTED);
53 
54 		// check the value
55 		printf("[%ld] parent: after exit child: globalVar: \"%s\"\n",
56 			parent, globalVar);
57 
58 		if (strcmp(globalVar, kInitialValue) == 0)
59 			printf("test OK\n");
60 		else
61 			printf("test FAILED: child process changed parent's memory!\n");
62 	}
63 
64 	return 0;
65 }
66