4

MPI communicator is created in Fortran and passed to C which in turn returns a pointer (c_ptr) to the C communicator. This is done to avoid constructing C communicator for every C function. But when I try to reuse the C communicator in ReuseComm I get segmentation fault.

Fortran module

module mymodule

    use mpi
    use, intrinsic :: ISO_C_Binding, only: c_ptr, c_null_ptr

    implicit none
    private

    interface

        subroutine reuse_comm(comm) bind(C, name="reuse_comm")
            import c_ptr
            implicit none
            type(c_ptr), intent(in) :: comm
        end subroutine reuse_comm

        function f_MPI_Comm_f2c(comm) result(optr) bind(C, name="f_MPI_Comm_f2c")
            import c_ptr
            implicit none
            integer, intent(in) :: comm
            type(c_ptr) :: optr
        end function f_MPI_Comm_f2c

    end interface    

    type(c_ptr), save :: ccomm = c_null_ptr

    public :: CreateCcomm, ReuseComm, ccomm

    CONTAINS

        subroutine CreateCcomm(com)
            integer, intent(in) :: com
            ccomm = f_MPI_Comm_f2c(com)
        end subroutine CreateCcomm

        subroutine ReuseComm()
            call reuse_comm(ccomm)
        end subroutine ReuseComm

end module mymodule

Fortran driver

program main

use mpi
use Tailor_module, only : CreateCcomm, ReuseComm, ccomm
use, intrinsic :: ISO_C_Binding, only: c_ptr
IMPLICIT NONE

integer error 

call MPI_Init(error)
call CreateCcomm(MPI_COMM_WORLD)
call ReuseComm()
call MPI_Finalize (error)

end

C++

extern "C"
{
    MPI_Comm* f_MPI_Comm_f2c(MPI_Fint* f_handle)
    {
        MPI_Comm* comm;
        comm = (MPI_Comm*)malloc(sizeof(MPI_Comm));
        *comm = MPI_Comm_f2c(*f_handle);
        assert(*comm != MPI_COMM_NULL);

        int sizep = -1;
        MPI_Comm_size(*comm, &sizep);
        std::cout << "sizep: " << sizep << std::endl; // good, prints correct output.

        return comm;
    }

    void reuse_comm(MPI_Comm* comm)
    {
        assert(comm != NULL);
        assert(*comm != MPI_COMM_NULL);

        int sizep = -1;
        MPI_Comm_size(*comm, &sizep); // causes seg fault.
        std::cout << "sizep: " << sizep << std::endl;
    }
}
Artyer
  • 31,034
  • 3
  • 47
  • 75
Shibli
  • 5,879
  • 13
  • 62
  • 126
  • 2
    Should it be `reuse_comm(MPI_Comm** comm)` ? Note `MPI_Comm_f2c()` is very efficient in Open MPI (simple array access) so unless you have evidence this is a bottleneck, you should probably save your efforts for some more time consuming tasks. – Gilles Gouaillardet Jul 05 '19 at 11:57
  • That solved problem. I can't thank you enough. Documentation is very scarce on the net. – Shibli Jul 05 '19 at 12:11

0 Answers0