Here is the basic setup:
- I have a Win32 program called callfork_demo.exe that loads the function call_fork() from the DLL callfork.dll. It then prints some output, calls call_fork(), then prints some more output, and terminates.
- The DLL being loaded, callfork.dll, is a Winelib DLL. It exposes just one function, call_fork(), which is just a wrapper around the unistd.h fork() function with some additional printf's for debugging.
Here is the basic behavior I am trying to create with any interleaving of the last six lines:
[target, pre-fork] fork check!
[proxy lib, pre-fork] calling call_fork()!
[linux lib, pre-fork] pid = 24
<--- non-determinism starts here --->
[linux lib, post-fork] I'm the parent
[proxy lib, post-fork] I'm the parent coming back
[target, post-fork] I'm the parent in the target, finishing up!
[linux lib, post-fork] I'm the child
[proxy lib, post-fork] I'm the child coming back
[target, post-fork] I'm the child in the target, finishing up!
Here is the behavior I am currently getting, however:
[target, pre-fork] fork check!
[proxy lib, pre-fork] calling call_fork()!
[linux lib, pre-fork] pid = 24
<--- non-determinism starts here --->
[linux lib, post-fork] I'm the parent
[proxy lib, post-fork] I'm the parent coming back
[target, post-fork] I'm the parent in the target, finishing up!
[linux lib, post-fork] I'm the child
[proxy lib, post-fork] I'm the child coming back
Note that the difference here is the parent returns to the target just fine and finishes execution, but the child never makes it back to the target.
Basically, I just want to be able to fork a Windows process running under Wine, and my current method to do so is by wrapping the unistd.h library into a Winelib DLL and calling fork from it. I am sure there is something I am misunderstanding about why my current approach isn't working, so if someone can point out my error and explain why, it would be much appreciated.
I'll attach the full code and build script below. Thank you!
callfork_demo.c
Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
typedef int(*call_fork_t)();
#pragma clang optimize off
#pragma GCC optimize("O0")
int main(int argc, char **argv) {
HINSTANCE HInst = LoadLibrary("callfork.dll");
if(HInst == NULL) {
printf("ERROR: Could not load library\n");
return 1;
}
call_fork_t call_fork = (call_fork_t)GetProcAddress(HInst,"call_fork");
if(call_fork == NULL) {
printf("ERROR: Could not load functions\n");
return 1;
}
printf("[target, pre-fork] fork check!\n");
int pid = call_fork();
printf("[target, post-fork] mypid = %d\n",pid);
printf("[target, post-fork] Returning!\n");
return 0;
}
Code: Select all
#include "callfork.h"
int proxy_call_fork() {
printf("[proxy lib, pre-fork] calling call_fork()!\n");
int pid = call_fork();
printf("[proxy lib, post-fork] coming back, ret val = %d, pid = %d\n",pid,getpid());
return pid;
}
Code: Select all
#include "callfork.h"
int call_fork() {
printf("[linux lib, pre-fork] pid = %d\n",getpid());
int pid = fork();
printf("[linux lib, post-fork] ret val = %d, pid = %d\n",pid,getpid());
return pid;
}
Code: Select all
#ifndef CALLFORK_H
#define CALLFORK_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int call_fork();
#endif
Code: Select all
#!/bin/bash
MINGWCC=i686-w64-mingw32-gcc-win32
CC=clang
WCC=winegcc
# Build libraries
$CC -m32 -fPIC -c callfork.c
$CC -m32 -fPIC -shared -o libcallfork.so callfork.o
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`
# Build proxy DLL
$CC -m32 -fPIC -c proxy_callfork.c
$WCC -m32 -fPIC -shared -L. -B/home/osboxes/wine/tools/winebuild --sysroot=/home/osboxes/wine ./proxy_callfork.dll.spec -o proxy_callfork.dll.so proxy_callfork.o /home/osboxes/wine/libs/port/libwine_port.a -lcallfork
cp proxy_callfork.dll.so callfork.dll
# Build target
$MINGWCC -m32 -fPIC -o callfork_demo.exe callfork_demo.c
# Clean
rm -f *.o