Ask Your Question

Revision history [back]

highgui and fork()

Hi all!

I'm using OpenCV in a project at work, I won't enter in details because the algorithm is irrelevant for my problem. The thing is, my program uses one or more processes as it listens on a socket and then accept incoming connections by fork()-ing to dispatch clients into child programs. After the call to fork() trying to display an image with imshow() just doesn't work.

Calling to imshow() and then waitKey(0) doesn't display anything and then the window hangs (on Ubuntu, it becomes "shadowed" which means that window isn't responding to the WM anymore).

As I need to be able to see some images (results of my algorithm), I need to be able to successfully display some images that a child program generates. I also noticed that some errors appears when calling waitKey(), imshow() by itself doesn't show errors neither works as expected.

1) Is it possible to call imshow() and waitKey() from a child after fork()?

2) Is it possible to do the same from the parent after calling fork()? It seems to be problematic too.

3) Is there another way to display images from the child?

4) Why does this happens? I want to know because I want to get a deeper understanding in this and why this fails to avoid future problems and well... to learn :)

In case it helps, I'm attaching some code that I used to reproduce this issue.

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
//#include <thread>
#include <X11/Xlib.h>

/* Test cases:
 * compile with values from 1 to 4 to check where
 * the program is failing
 */
#define TEST_CASE 1

using namespace cv;

int main(int argc, char **argv) {

    Mat img;
    pid_t pid;

    if (argc > 1)
        img = imread(argv[1]);

    // XInitThreads(); /* I don't know if I have to use this one */
    imshow("first one", img);

    waitKey(0);
    pid = fork();


    /* since xorg may show error messages asynchronously 
     * we're addin a little delay */
#if TEST_CASE == 1
    fprintf(stderr, "first call to waitKey(0) after fork()\n");
    waitKey(0);
    usleep(100000);
    fprintf(stderr, "after fork() and waitKey(0)\n");
#endif

    if (pid < 0) {
        fprintf(stderr, "Error while forking..\n");
        exit(-1);
    }

    if (pid == 0) {
        /* child */
#if ((TEST_CASE == 2) || (TEST_CASE == 4))
        /* child process will just display a black image */
        Mat black = Mat::zeros(img.rows, img.cols, img.type());
        fprintf(stderr, "Child before imshow\n");
        imshow("child", black);
        fprintf(stderr, "Child after imshow\n");
#endif
    } else {
        /* parent */
#if ((TEST_CASE == 3) || (TEST_CASE == 4))
        /* parent process will just display a white image */
        Mat white = Mat::ones(img.rows, img.cols, img.type());
        fprintf(stderr, "Parent before imshow\n");
        imshow("parent", white);
        fprintf(stderr, "Parent after imshow\n");
#endif
    }

    waitKey(0);

    return 0;
}

Program output is this:

$ ./forking ../../images/malezas.jpg 
first call to waitKey(0) after fork()
first call to waitKey(0) after fork()
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
forking: ../../src/xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
forking: ../../src/xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
Aborted (core dumped)
$

You can change the value of TEST_CASE on compile time to check for different errors if you want to test it.

Thanks in advance.