Support of subprocesses (in C, with fork())?

Hello!

I am working in the development of the TTK library, in C++. For some reason, we need to create real subprocesses (threads cannot do the thing we want).
However when I test on some filter I am developping, I have a segfault. More precisely, I create one subprocess. The parent process waits for the child to terminate, the child does trivial things and then executes “exit(0)”;
This causes the segfault. I investigated it with gdb (not building paraview in debug mode, though), asked it to follow the child process. And it happens that gdb locates the segfault precisely at the execution of the line “exit(0);” from the child process.

This caused me to wonder wheter using fork() (subprocesses) is allowed by paraview or if it is not supported.

Have a nice day,
Alexandre

You want to try there.

This caused me to wonder wheter using fork() (subprocesses) is allowed by paraview or if it is not supported.

I dont see why it would not be.

@Charles_Gueunet

this is a game changer. right now, if you want to make a video, you have wait… one cpu to work. Image you can do subprocess to use all your cpu, this definitely will enhance the productivity.

You can use fork in your process as long as you:

  1. Do not introduce data race
  2. Do not make MPI call in the fork

The first point is the usual asynchronous issue. As ParaView won’t be aware of the thread, you need to ensure data validity for both workers.

The second is due to how we initialize MPI in ParaView. Theoretically, we should not even be allowed to launch any threads when MPI is used but fortunately all MPI implementations assume MPI_INIT_THREAD even when only MPI_INIT is given.

Hello,
Thank you for your detailed answer. After second thoughts, I think I got the reasons. I fork from inside an MP thread. This is not “making MPI calls in the fork”, but “forking from an MPI thread”, so I assume it causes the same problem.

Hello,
I guess I have a final question: I resolved my problems, everything is running almost fine. But eath time a children process terminates (I call exit(0)) I have somme red error log (segfault caught) in paraview. Do you know how to avoid that (the process exits with return code 0, so I do not understant why it causes a segfault).
Here is the log + the top of the backtrace:

Exiting child 4

Loguru caught a signal: SIGSEGV
Stack trace:
[truncated]
123     0x55555555cdd5 /usr/local/bin/paraview(+0x8dd5) [0x55555555cdd5]
122     0x7ffff7dbb84a __libc_start_main + 138
121     0x7ffff7dbb790 /usr/lib/libc.so.6(+0x23790) [0x7ffff7dbb790]
120     0x55555556401d /usr/local/bin/paraview(+0x1001d) [0x55555556401d]
119     0x7ffff58912f9 QCoreApplication::exec() + 153
118     0x7ffff588668c QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 300
117     0x7ffff58d8d3c QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 108
116     0x7fffe4f0e1a2 g_main_context_iteration + 50
115     0x7fffe4f6c219 /usr/lib/libglib-2.0.so.0(+0xb7219) [0x7fffe4f6c219]
114     0x7fffe4f0f53b g_main_context_dispatch + 411
113     0x7ffff58d8bc2 /usr/lib/libQt5Core.so.5(+0x2d8bc2) [0x7ffff58d8bc2]
112     0x7ffff58d8583 QTimerInfoList::activateTimers() + 931
111     0x7ffff588e028 QCoreApplication::notifyInternal2(QObject*, QEvent*) + 296
110     0x7ffff6f78b5c QApplicationPrivate::notify_helper(QObject*, QEvent*) + 156
109     0x7ffff58b1c26 QObject::event(QEvent*) + 470
108     0x7ffff7cda599 pqTimer::timerEvent(QTimerEvent*) + 35
107     0x7ffff58c109f QTimer::timeout(QTimer::QPrivateSignal) + 63
106     0x7ffff58becf0 /usr/lib/libQt5Core.so.5(+0x2becf0) [0x7ffff58becf0]
105     0x7ffff76d2534 /usr/local/bin/../lib/libpqApplicationComponents-pv5.11.so.1(+0xd2534) [0x7ffff76d2534]
104     0x7ffff774ed3e pqCommandLineOptionsBehavior::processCommandLineOptions() + 32
103     0x7ffff774fa42 pqCommandLineOptionsBehavior::processState() + 284
102     0x7ffff77d3137 pqLoadStateReaction::loadState(QString const&, bool, pqServer*) + 1089
101     0x7ffff51e3ff4 vtkSMLoadStateOptionsProxy::Load() + 1882
100     0x7ffff52c1ee6 vtkSMSessionProxyManager::LoadXMLState(vtkPVXMLElement*, vtkSMStateLoader*, bool) + 226
99      0x7ffff52f3923 vtkSMStateLoader::LoadState(vtkPVXMLElement*, bool) + 1439
98      0x7ffff52f43b9 vtkSMStateLoader::LoadStateInternal(vtkPVXMLElement*) + 2181
97      0x7ffff52f0f66 vtkSMStateLoader::RegisterProxy(unsigned int, vtkSMProxy*) + 264
96      0x7ffff52f1154 vtkSMStateLoader::RegisterProxyInternal(char const*, char const*, vtkSMProxy*) + 426
95      0x7ffff52c08d0 vtkSMSessionProxyManager::RegisterProxy(char const*, char const*, vtkSMProxy*) + 1734
94      0x7fffef1b0997 vtkObject::InvokeEvent(unsigned long, void*) + 61
93      0x7fffef1b03ed /usr/local/bin/../lib/libvtkCommonCore-pv5.11.so.1(+0x9b03ed) [0x7fffef1b03ed]
92      0x7fffeefb1d65 vtkCallbackCommand::Execute(vtkObject*, unsigned long, void*) + 71
91      0x7ffff67be0b2 /usr/local/bin/../lib/libvtkGUISupportQt-pv5.11.so.1(+0x650b2) [0x7ffff67be0b2]
90      0x7ffff67be125 /usr/local/bin/../lib/libvtkGUISupportQt-pv5.11.so.1(+0x65125) [0x7ffff67be125]
89      0x7ffff6782e7a /usr/local/bin/../lib/libvtkGUISupportQt-pv5.11.so.1(+0x29e7a) [0x7ffff6782e7a]
88      0x7ffff58becf0 /usr/lib/libQt5Core.so.5(+0x2becf0) [0x7ffff58becf0]
87      0x7ffff6494230 /usr/local/bin/../lib/libpqCore-pv5.11.so.1(+0x94230) [0x7ffff6494230]
86      0x7ffff65b34f1 pqServerManagerObserver::proxyRegistered(vtkObject*, unsigned long, void*, void*, vtkCommand*) + 263
85      0x7ffff6494a00 pqServerManagerObserver::proxyRegistered(QString const&, QString const&, vtkSMProxy*) + 130
84      0x7ffff58becf0 /usr/lib/libQt5Core.so.5(+0x2becf0) [0x7ffff58becf0]
83      0x7ffff64918eb /usr/local/bin/../lib/libpqCore-pv5.11.so.1(+0x918eb) [0x7ffff64918eb]
82      0x7ffff65ae98e pqServerManagerModel::onProxyRegistered(QString const&, QString const&, vtkSMProxy*) + 2164
81      0x7ffff64931d4 pqServerManagerModel::proxyAdded(pqProxy*) + 94
80      0x7ffff58becf0 /usr/lib/libQt5Core.so.5(+0x2becf0) [0x7ffff58becf0]
79      0x7ffff68fcf1d /usr/local/bin/../lib/libpqComponents-pv5.11.so.1(+0xfcf1d) [0x7ffff68fcf1d]
78      0x7ffff6b1eeaa pqTabbedMultiViewWidget::proxyAdded(pqProxy*) + 166
77      0x7ffff6b1f4cb pqTabbedMultiViewWidget::createTab(vtkSMViewLayoutProxy*) + 51
76      0x7ffff6b1d54c /usr/local/bin/../lib/libpqComponents-pv5.11.so.1(+0x31d54c) [0x7ffff6b1d54c]
75      0x7ffff6b1c7ef pqTabbedMultiViewWidget::pqTabWidget::addAsTab(pqMultiViewWidget*, pqTabbedMultiViewWidget*) + 197
74      0x7ffff714946d QTabWidget::insertTab(int, QWidget*, QString const&) + 77
73      0x7ffff714939b QTabWidget::insertTab(int, QWidget*, QIcon const&, QString const&) + 43
72      0x7ffff6f99f22 QStackedLayout::insertWidget(int, QWidget*) + 34
71      0x7ffff6f92700 QLayout::addChildWidget(QWidget*) + 432
70      0x7ffff6fb024c QWidget::setParent(QWidget*, QFlags<Qt::WindowType>) + 1452
69      0x7ffff6fa8215 /usr/lib/libQt5Widgets.so.5(+0x1a8215) [0x7ffff6fa8215]
68      0x7ffff6fa8215 /usr/lib/libQt5Widgets.so.5(+0x1a8215) [0x7ffff6fa8215]
67      0x7ffff6fa8215 /usr/lib/libQt5Widgets.so.5(+0x1a8215) [0x7ffff6fa8215]
66      0x7ffff6fa8215 /usr/lib/libQt5Widgets.so.5(+0x1a8215) [0x7ffff6fa8215]
65      0x7ffff6fa8215 /usr/lib/libQt5Widgets.so.5(+0x1a8215) [0x7ffff6fa8215]
64      0x7ffff6fa8240 /usr/lib/libQt5Widgets.so.5(+0x1a8240) [0x7ffff6fa8240]
63      0x7ffff588e028 QCoreApplication::notifyInternal2(QObject*, QEvent*) + 296
62      0x7ffff6f78b5c QApplicationPrivate::notify_helper(QObject*, QEvent*) + 156
61      0x7ffff67998c0 QVTKOpenGLNativeWidget::event(QEvent*) + 96
60      0x7ffff6fd37f3 QOpenGLWidget::event(QEvent*) + 291
59      0x7ffff6fa33eb QWidgetPrivate::sendPaintEvent(QRegion const&) + 59
58      0x7ffff588e028 QCoreApplication::notifyInternal2(QObject*, QEvent*) + 296
57      0x7ffff6f78b5c QApplicationPrivate::notify_helper(QObject*, QEvent*) + 156
56      0x7ffff67998c0 QVTKOpenGLNativeWidget::event(QEvent*) + 96
55      0x7ffff6faf514 QWidget::event(QEvent*) + 1956
54      0x7ffff6fcc755 /usr/lib/libQt5Widgets.so.5(+0x1cc755) [0x7ffff6fcc755]
53      0x7ffff6799715 QVTKOpenGLNativeWidget::paintGL() + 225
52      0x7ffff679cf63 QVTKRenderWindowAdapter::paint() + 63
51      0x7ffff679f308 /usr/local/bin/../lib/libvtkGUISupportQt-pv5.11.so.1(+0x46308) [0x7ffff679f308]
50      0x7ffff36315d4 vtkRenderWindowInteractor::Render() + 110
49      0x7fffef1b0997 vtkObject::InvokeEvent(unsigned long, void*) + 61
48      0x7fffef1b03ed /usr/local/bin/../lib/libvtkCommonCore-pv5.11.so.1(+0x9b03ed) [0x7fffef1b03ed]
47      0x7fffec638228 /usr/local/bin/../lib/libvtkRemotingViews-pv5.11.so.1(+0x438228) [0x7fffec638228]
46      0x7fffec6374eb vtkSMViewProxyInteractorHelper::Execute(vtkObject*, unsigned long, void*) + 629
45      0x7fffec637ab2 vtkSMViewProxyInteractorHelper::Render() + 680
44      0x7fffec634199 vtkSMViewProxy::InteractiveRender() + 147
43      0x7fffec5a5341 vtkSMRenderViewProxy::Update() + 63
42      0x7fffec6344c6 vtkSMViewProxy::Update() + 410
41      0x7ffff526c590 vtkSMProxy::ExecuteStream(vtkClientServerStream const&, bool, unsigned int) + 170
40      0x7ffff50f2556 vtkPVSessionBase::ExecuteStream(unsigned int, vtkClientServerStream const&, bool) + 96
39      0x7ffff50f6844 vtkPVSessionCore::ExecuteStream(unsigned int, vtkClientServerStream const&, bool) + 516
38      0x7ffff50f6a94 vtkPVSessionCore::ExecuteStreamInternal(vtkClientServerStream const&, bool) + 250
37      0x7ffff546b955 vtkClientServerInterpreter::ProcessStream(vtkClientServerStream const&) + 47
36      0x7ffff546baf2 vtkClientServerInterpreter::ProcessOneMessage(vtkClientServerStream const&, int) + 364
35      0x7ffff546c60f vtkClientServerInterpreter::ProcessCommandInvoke(vtkClientServerStream const&, int) + 513
34      0x7ffff546e270 vtkClientServerInterpreter::CallCommandFunction(char const*, vtkObjectBase*, char const*, vtkClientServerStream const&, vtkClientServerStream&) + 878
33      0x7fffecdbc51d vtkPVRenderViewCommand(vtkClientServerInterpreter*, vtkObjectBase*, char const*, vtkClientServerStream const&, vtkClientServerStream&, void*) + 31812
32      0x7fffec4dfb27 vtkPVRenderView::Update() + 227
31      0x7fffec530a25 vtkPVView::Update() + 355
30      0x7fffec531187 vtkPVView::CallProcessViewRequest(vtkInformationRequestKey*, vtkInformation*, vtkInformationVector*) + 249
29      0x7fffec3b8af9 vtkGeometryRepresentationWithFaces::ProcessViewRequest(vtkInformationRequestKey*, vtkInformation*, vtkInformation*) + 49
28      0x7fffec3a8936 vtkGeometryRepresentation::ProcessViewRequest(vtkInformationRequestKey*, vtkInformation*, vtkInformation*) + 66
27      0x7fffec447369 vtkPVDataRepresentation::ProcessViewRequest(vtkInformationRequestKey*, vtkInformation*, vtkInformation*) + 595
26      0x7ffff10602cd vtkAlgorithm::Update() + 77
25      0x7ffff1060302 vtkAlgorithm::Update(int) + 50
24      0x7ffff11429a3 vtkStreamingDemandDrivenPipeline::Update(int) + 51
23      0x7ffff1142b1a vtkStreamingDemandDrivenPipeline::Update(int, vtkInformationVector*) + 372
22      0x7ffff10775ef vtkDemandDrivenPipeline::UpdateData(int) + 913
21      0x7fffec449452 vtkPVDataRepresentationPipeline::ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 138
20      0x7ffff114278a vtkStreamingDemandDrivenPipeline::ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 3238
19      0x7ffff1076cad vtkDemandDrivenPipeline::ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 1259
18      0x7fffec4493c4 vtkPVDataRepresentationPipeline::ForwardUpstream(vtkInformation*) + 60
17      0x7ffff106dcd5 vtkCompositeDataPipeline::ForwardUpstream(vtkInformation*) + 963
16      0x7ffff114278a vtkStreamingDemandDrivenPipeline::ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 3238
15      0x7ffff1076cad vtkDemandDrivenPipeline::ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 1259
14      0x7ffff106dcd5 vtkCompositeDataPipeline::ForwardUpstream(vtkInformation*) + 963
13      0x7ffff114278a vtkStreamingDemandDrivenPipeline::ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 3238
12      0x7ffff1076db7 vtkDemandDrivenPipeline::ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 1525
11      0x7ffff106aa09 vtkCompositeDataPipeline::ExecuteData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 1663
10      0x7ffff107780a vtkDemandDrivenPipeline::ExecuteData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 112
9       0x7ffff108147d vtkExecutive::CallAlgorithm(vtkInformation*, int, vtkInformationVector**, vtkInformationVector*) + 199
8       0x7fffd35706f3 ttkMapper::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 2817
7       0x7fffd357e905 int ttk::Mapper::execute<float, ttk::ExplicitTriangulation>(int*, int*, std::vector<std::array<float, 3ul>, std::allocator<std::array<float, 3ul> > >&, std::vector<int>&, std::vector<std::set<int, std::less<int> >, std::allocator<std::set<int, std::less<int> > > >&, float*, ttk::Mapper::Matrix const&, float const*, ttk::ExplicitTriangulation const&) const + 4861
6       0x7fffd35ed762 int ttk::Mapper::reEmbedMapper<ttk::ExplicitTriangulation>(std::vector<std::array<float, 3ul>, std::allocator<std::array<float, 3ul> > >&, float*, ttk::Mapper::Matrix const&, int const*, std::vector<std::set<int, std::less<int> >, std::allocator<std::set<int, std::less<int> > > > const&, std::vector<std::vector<int>, std::allocator<std::vector<int> > > const&, std::vector<int> const&, ttk::ExplicitTriangulation const&) const + 6526
5       0x7ffff7dd35b0 /usr/lib/libc.so.6(+0x3b5b0) [0x7ffff7dd35b0]
4       0x7ffff7dd3445 /usr/lib/libc.so.6(+0x3b445) [0x7ffff7dd3445]
3       0x7fffa60bbdb4 /usr/lib/dri/iris_dri.so(+0xbbdb4) [0x7fffa60bbdb4]
2       0x7fffa60bbc98 /usr/lib/dri/iris_dri.so(+0xbbc98) [0x7fffa60bbc98]
1       0x7ffff7e1f5c2 /usr/lib/libc.so.6(+0x875c2) [0x7ffff7e1f5c2]
0       0x7ffff7dd0f50 /usr/lib/libc.so.6(+0x38f50) [0x7ffff7dd0f50]
(  14.970s) [paraview        ]                       :0     FATL| Signal: SIGSEGV
Thread 2.1 "paraview" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffe3932c80 (LWP 169645)]
__pthread_clockjoin_ex (threadid=140735248582336, thread_return=0x7fffffff9930, clockid=0, 
    abstime=0x0, block=true) at pthread_join_common.c:43
43	  if (INVALID_NOT_TERMINATED_TD_P (pd))
(gdb) bt
#0  __pthread_clockjoin_ex
    (threadid=140735248582336, thread_return=0x7fffffff9930, clockid=0, abstime=0x0, block=true) at pthread_join_common.c:43
#1  0x00007fffa60bbc98 in  () at /usr/lib/dri/iris_dri.so
#2  0x00007fffa60bbdb4 in  () at /usr/lib/dri/iris_dri.so
#3  0x00007ffff7dd3445 in __run_exit_handlers
    (status=0, listp=0x7ffff7f70660 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:108
#4  0x00007ffff7dd35b0 in __GI_exit (status=<optimized out>) at exit.c:138
#5  0x00007fffd35ed762 in ttk::Mapper::reEmbedMapper<ttk::ExplicitTriangulation>(std::vector<std::array<float, 3ul>, std::allocator<std::array<float, 3ul> > >&, float*, ttk::Mapper::Matrix const&, int const*, std::vector<std::set<int, std::less<int>, std::allocator<int> >, std::allocator<std::set<int, std::less<int>, std::allocator<int> > > > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<int, std::allocator<int> > const&, ttk::ExplicitTriangulation const&) const
    (this=0x55555ad0d810, compBaryCoords=std::vector of length 65, capacity 100 = {...}, outputPointsCoords=0x5555585f1370, distMat=..., outputConnComp=0x5555632f88e0, compArcs=std::vector of length 65, capacity 100 = {...}, connCompEdges=std::vector of length 65, capacity 65 = {...}, connCompBucket=std::vector of length 65, capacity 65 = {...}, triangulation=...)

If it may help, some context of frame 3:

#3  0x00007ffff7dd3445 in __run_exit_handlers (status=0, listp=0x7ffff7f70660 <__exit_funcs>, 
    run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:108
108		      cxafct (arg, status);
(gdb) p arg
$1 = (void *) 0x0
(gdb) p status
$2 = 0

Frame 4:
#4  0x00007ffff7dd35b0 in __GI_exit (status=<optimized out>) at exit.c:138
138	  __run_exit_handlers (status, &__exit_funcs, true, true);

Frame 5 (my code):
(gdb) f 5
#5  0x00007fffd35ed762 in ttk::Mapper::reEmbedMapper<ttk::ExplicitTriangulation> (
    this=0x55555ad0d810, compBaryCoords=std::vector of length 65, capacity 100 = {...}, 
    outputPointsCoords=0x5555585f1370, distMat=..., outputConnComp=0x5555632f88e0, 
    compArcs=std::vector of length 65, capacity 100 = {...}, 
    connCompEdges=std::vector of length 65, capacity 65 = {...}, 
    connCompBucket=std::vector of length 65, capacity 65 = {...}, triangulation=...)
992	    exit(0);

Hello!
I found time to test the support of subprocess and it seems that there is an actual problem. I made a minimal example (using a bit of TTK macros, but they can be removed, I never programmed a pure vtk filter without TTK) where I basically fork, the child waits for 3 seconds then exit(0), and the parent wait() its child.

Running it without Paraview (en C++, with VTK) works fine. Running it with paraview gives the following red messages in the console:

Loguru caught a signal: SIGINT
Stack trace:
10 0x560b071cb665 paraview(+0x8665) [0x560b071cb665]
9 0x7f21f5d5690a __libc_start_main + 138
8 0x7f21f5d56850 /usr/lib/libc.so.6(+0x23850) [0x7f21f5d56850]
7 0x560b071cb4b3 paraview(+0x84b3) [0x560b071cb4b3]
6 0x7f21f3a9acc3 QCoreApplication::exec() + 147
5 0x7f21f3a99824 QEventLoop::exec(QFlagsQEventLoop::ProcessEventsFlag) + 308
4 0x7f21f3ae9f0c QEventDispatcherGlib::processEvents(QFlagsQEventLoop::ProcessEventsFlag) + 108
3 0x7f21e950e032 g_main_context_iteration + 50
2 0x7f21e956da9f /usr/lib/libglib-2.0.so.0(+0xb7a9f) [0x7f21e956da9f]
1 0x7f21f5e30c0f poll + 79
0 0x7f21f5d6cab0 /usr/lib/libc.so.6(+0x39ab0) [0x7f21f5d6cab0]
( 2.188s) [paraview ] :0 FATL| Signal: SIGINT

Here are the .h and .ccp file of the vtkfilter (doing almost nothing).

Could anyone investigate this? We rely in the use of subprocesses to speedup some filter for vtk/paraview, we obtain a good speedup but get this red message in the console.
ttkTestFork.cpp (1.4 KB)
ttkTestFork.h (684 Bytes)

@Charles_Gueunet or @mwestphal maybe?

Hi @atalon-lip6

I’m afraid it may require some effort to look into this on my side.

Best,