0
votes

I wrote a program "run_coffee.c" to implement fork() and exec() system calls. It fundamentally calls exec to start another process "coffee" built through "coffee.c" multiple times. The problem is I am running this program on cygwin64 in windows environment and it keeps failing with the following error - **

error while loading shared libraries: ?: cannot open shared object file: no such file or directory

**

I also ran cygcheck to see wether dependencies are being met or not. This is the output -

C:\cygwin64\home\Admin\run_coffee.exe C:\cygwin64\bin\cygwin1.dll

C:\Windows\system32\KERNEL32.dll

C:\Windows\system32\API-MS-Win-Core-RtlSupport-L1-1-0.dll

C:\Windows\system32\ntdll.dll C:\Windows\system32\KERNELBASE.dll

C:\Windows\system32\API-MS-Win-Core-ProcessThreads-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Heap-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Memory-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Handle-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Synch-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-File-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-IO-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-ThreadPool-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-LibraryLoader-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-NamedPipe-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Misc-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-SysInfo-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Localization-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-ProcessEnvironment-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-String-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Debug-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-ErrorHandling-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Fibers-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Util-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Profile-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Security-Base-L1-1-0.dll

No error or unmet dependency showed up so I guess all dependencies are being met. So what is causing this problem? Please Help.

Here are the two programs -

coffee.c

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char *argv[])
{
    char  *w = getenv("EXTRA");
    if (!w)
        w = getenv("FOOD");
    if (!w)
        w = argv[argc-1];
    char *c = getenv("EXTRA");
    if (!c)
        c = argv[argc-1];
    printf("%s with %s\n", c, w);
    return 0;
}

run_coffee.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

struct food_options
{
    char *food;
    char *extra;
};

int main()
{
    int i;
    char **env;
    env[0] = (char*)malloc(sizeof(char) * 20);
    env[1] = (char*)malloc(sizeof(char) * 20);
    env[2] = (char*)malloc(sizeof(char) * 20);
    struct food_options *opts = (struct food_options *)malloc(sizeof(struct food_options) * 3);
    opts[0].food = "coffee";
    opts[0].extra = "donuts";
    opts[1].food = "fish";
    opts[1].extra = "chips";
    opts[2].food = "kabab";
    opts[2].extra = "parantha";



    for (i = 0; i < 3; i++)
    {
        pid_t pid = fork();
        if (pid == -1)
        {
            fprintf(stderr, "Cannot fork process. Fatal Error %s\n", strerror(errno));
            return 1;
        }

        else if (!pid)
        {
            sprintf(env[0], "FOOD=%s", opts[0].food);
            sprintf(env[1], "EXTRA=%s", opts[0].extra);
            env[2] = NULL;
            if (execle("coffee.exe","coffee.exe",NULL,env) == -1)
            {
                fprintf(stderr, "Cannot execute coffee.exe. Error %s\n", strerror(errno));
            }
        }
    }
    free(opts);
    free(env[0]);
    free(env[1]);
    free(env[2]);
    return 0;
}
1
You should use a POSIX system (like Linux) to play with fork; don't expect it to faithfully emulated by Cygwin on Windows.Basile Starynkevitch
I know that. But Cygwin claims to create a linux like environment in windows, doesn't it?Yasser Hussain
I believe the evil is in the details. You probably cannot exactly emulate POSIX on Windows. So learn well Linux and only when you have good programs on Linux try to painfully port them to Cygwin.Basile Starynkevitch
Fair point. Then what do you suggest should I do to make it work.Yasser Hussain
Install Linux on your laptop. Compile with gcc -Wall -Wextra -g on Linux. Debug using gdb and strace on Linux.Basile Starynkevitch

1 Answers

0
votes

There is a memory bug in your program which can cause undefined behavior: you declared env to be an array of char*'s, but you did not initialize env. Hence, env[0], env[1], and env[2] point to random locations in memory. When you do sprintf(env[0], ...) and sprintf(env[1], ...), you are writing data to some random location in memory (where ever env[0] and env[1] points to). This can cause almost anything to happen, including modification of the names of libraries, making you unable to load them.