Date: 2021-03-03T22:25:31+00:00

Actual source code: send.c
petsc-3.14.5 2021-03-03
Report Typos and Errors

      2: #include <petscsys.h>

      4: #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
      5: /* Some systems have inconsistent include files that use but do not
      6:    ensure that the following definitions are made */
      7: typedef unsigned char   u_char;
      8: typedef unsigned short  u_short;
      9: typedef unsigned short  ushort;
     10: typedef unsigned int    u_int;
     11: typedef unsigned long   u_long;
     12: #endif

     14: #include <errno.h>
     15: #include <ctype.h>
     16: #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
     17: #include <machine/endian.h>
     18: #endif
     19: #if defined(PETSC_HAVE_UNISTD_H)
     20: #include <unistd.h>
     21: #endif
     22: #if defined(PETSC_HAVE_SYS_SOCKET_H)
     23: #include <sys/socket.h>
     24: #endif
     25: #if defined(PETSC_HAVE_SYS_WAIT_H)
     26: #include <sys/wait.h>
     27: #endif
     28: #if defined(PETSC_HAVE_NETINET_IN_H)
     29: #include <netinet/in.h>
     30: #endif
     31: #if defined(PETSC_HAVE_NETDB_H)
     32: #include <netdb.h>
     33: #endif
     34: #if defined(PETSC_HAVE_FCNTL_H)
     35: #include <fcntl.h>
     36: #endif
     37: #if defined(PETSC_HAVE_IO_H)
     38: #include <io.h>
     39: #endif
     40: #if defined(PETSC_HAVE_WINSOCK2_H)
     41: #include <Winsock2.h>
     42: #endif
     43: #include <sys/stat.h>
     44: #include <../src/sys/classes/viewer/impls/socket/socket.h>

     46: #if defined(PETSC_NEED_CLOSE_PROTO)
     47: PETSC_EXTERN int close(int);
     48: #endif
     49: #if defined(PETSC_NEED_SOCKET_PROTO)
     50: PETSC_EXTERN int socket(int,int,int);
     51: #endif
     52: #if defined(PETSC_NEED_SLEEP_PROTO)
     53: PETSC_EXTERN int sleep(unsigned);
     54: #endif
     55: #if defined(PETSC_NEED_CONNECT_PROTO)
     56: PETSC_EXTERN int connect(int,struct sockaddr*,int);
     57: #endif

     59: /*--------------------------------------------------------------*/
     60: static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
     61: {
     62:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
     63:   PetscErrorCode     ierr;

     66:   if (vmatlab->port) {
     67: #if defined(PETSC_HAVE_CLOSESOCKET)
     68:     closesocket(vmatlab->port);
     69: #else
     70:     close(vmatlab->port);
     71: #endif
     72:     if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"System error closing socket");
     73:   }
     74:   PetscFree(vmatlab);
     75:   return(0);
     76: }

     78: /*--------------------------------------------------------------*/
     79: /*@C
     80:     PetscSocketOpen - handles connected to an open port where someone is waiting.

     82:     Input Parameters:
     83: +    url - for example www.mcs.anl.gov
     84: -    portnum - for example 80

     86:     Output Paramater:
     87: .    t - the socket number

     89:     Notes:
     90:     Use close() to close the socket connection

     92:     Use read() or PetscHTTPRequest() to read from the socket

     94:     Level: advanced

     96: .seealso:   PetscSocketListen(), PetscSocketEstablish(), PetscHTTPRequest(), PetscHTTPSConnect()
     97: @*/
     98: PetscErrorCode  PetscOpenSocket(const char hostname[],int portnum,int *t)
     99: {
    100:   struct sockaddr_in sa;
    101:   struct hostent     *hp;
    102:   int                s = 0;
    103:   PetscErrorCode     ierr;
    104:   PetscBool          flg = PETSC_TRUE;
    105:   static int         refcnt = 0;

    108:   if (!(hp=gethostbyname(hostname))) {
    109:     perror("SEND: error gethostbyname: ");
    110:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error open connection to %s",hostname);
    111:   }
    112:   PetscMemzero(&sa,sizeof(sa));
    113:   PetscMemcpy(&sa.sin_addr,hp->h_addr_list[0],hp->h_length);

    115:   sa.sin_family = hp->h_addrtype;
    116:   sa.sin_port   = htons((u_short) portnum);
    117:   while (flg) {
    118:     if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) {
    119:       perror("SEND: error socket");  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
    120:     }
    121:     if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
    122: #if defined(PETSC_HAVE_WSAGETLASTERROR)
    123:       WSAGetLastError();
    124:       if (ierr == WSAEADDRINUSE)    (*PetscErrorPrintf)("SEND: address is in use\n");
    125:       else if (ierr == WSAEALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
    126:       else if (ierr == WSAEISCONN) {
    127:         (*PetscErrorPrintf)("SEND: socket already connected\n");
    128:         Sleep((unsigned) 1);
    129:       } else if (ierr == WSAECONNREFUSED) {
    130:         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
    131:         Sleep((unsigned) 1);
    132:       } else {
    133:         perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
    134:       }
    135: #else
    136:       if (errno == EADDRINUSE)    (*PetscErrorPrintf)("SEND: address is in use\n");
    137:       else if (errno == EALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
    138:       else if (errno == EISCONN) {
    139:         (*PetscErrorPrintf)("SEND: socket already connected\n");
    140:         sleep((unsigned) 1);
    141:       } else if (errno == ECONNREFUSED) {
    142:         refcnt++;
    143:         if (refcnt > 5) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"Connection refused by remote host %s port %d",hostname,portnum);
    144:         PetscInfo(NULL,"Connection refused in attaching socket, trying again\n");
    145:         sleep((unsigned) 1);
    146:       } else {
    147:         perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
    148:       }
    149: #endif
    150:       flg = PETSC_TRUE;
    151: #if defined(PETSC_HAVE_CLOSESOCKET)
    152:       closesocket(s);
    153: #else
    154:       close(s);
    155: #endif
    156:     } else flg = PETSC_FALSE;
    157:   }
    158:   *t = s;
    159:   return(0);
    160: }

    163: /*@C
    164:    PetscSocketEstablish - starts a listener on a socket

    166:    Input Parameters:
    167: .    portnumber - the port to wait at

    169:    Output Parameters:
    170: .     ss - the socket to be used with PetscSocketListen()

    172:     Level: advanced

    174: .seealso:   PetscSocketListen(), PetscOpenSocket()

    176: @*/
    177: PETSC_INTERN PetscErrorCode PetscSocketEstablish(int portnum,int *ss)
    178: {
    179:   static size_t      MAXHOSTNAME = 100;
    180:   char               myname[MAXHOSTNAME+1];
    181:   int                s;
    182:   PetscErrorCode     ierr;
    183:   struct sockaddr_in sa;
    184:   struct hostent     *hp;

    187:   PetscGetHostName(myname,sizeof(myname));

    189:   PetscMemzero(&sa,sizeof(struct sockaddr_in));

    191:   hp = gethostbyname(myname);
    192:   if (!hp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Unable to get hostent information from system");

    194:   sa.sin_family = hp->h_addrtype;
    195:   sa.sin_port   = htons((u_short)portnum);

    197:   if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error running socket() command");
    198: #if defined(PETSC_HAVE_SO_REUSEADDR)
    199:   {
    200:     int optval = 1; /* Turn on the option */
    201:     setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));
    202:   }
    203: #endif

    205:   while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
    206: #if defined(PETSC_HAVE_WSAGETLASTERROR)
    207:     WSAGetLastError();
    208:     if (ierr != WSAEADDRINUSE) {
    209: #else
    210:     if (errno != EADDRINUSE) {
    211: #endif
    212:       close(s);
    213:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error from bind()");
    214:     }
    215:   }
    216:   listen(s,0);
    217:   *ss = s;
    218:   return(0);
    219: }

    221: /*@C
    222:    PetscSocketListen - Listens at a socket created with PetscSocketEstablish()

    224:    Input Parameter:
    225: .    listenport - obtained with PetscSocketEstablish()

    227:    Output Parameter:
    228: .     t - pass this to read() to read what is passed to this connection

    230:     Level: advanced

    232: .seealso:   PetscSocketEstablish()
    233: @*/
    234: PETSC_INTERN PetscErrorCode PetscSocketListen(int listenport,int *t)
    235: {
    236:   struct sockaddr_in isa;
    237: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
    238:   size_t             i;
    239: #else
    240:   int                i;
    241: #endif

    244:   /* wait for someone to try to connect */
    245:   i = sizeof(struct sockaddr_in);
    246:   if ((*t = accept(listenport,(struct sockaddr*)&isa,(socklen_t*)&i)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"error from accept()\n");
    247:   return(0);
    248: }

    250: /*@C
    251:    PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket based server.

    253:    Collective

    255:    Input Parameters:
    256: +  comm - the MPI communicator
    257: .  machine - the machine the server is running on,, use NULL for the local machine, use "server" to passively wait for
    258:              a connection from elsewhere
    259: -  port - the port to connect to, use PETSC_DEFAULT for the default

    261:    Output Parameter:
    262: .  lab - a context to use when communicating with the server

    264:    Level: intermediate

    266:    Notes:
    267:    Most users should employ the following commands to access the
    268:    MATLAB PetscViewers
    269: $
    270: $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
    271: $    MatView(Mat matrix,PetscViewer viewer)
    272: $
    273: $                or
    274: $
    275: $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
    276: $    VecView(Vec vector,PetscViewer viewer)

    278:    Options Database Keys:
    279:    For use with  PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
    280:    PETSC_VIEWER_SOCKET_() or if
    281:     NULL is passed for machine or PETSC_DEFAULT is passed for port
    282: $    -viewer_socket_machine <machine>
    283: $    -viewer_socket_port <port>

    285:    Environmental variables:
    286: +   PETSC_VIEWER_SOCKET_PORT - portnumber
    287: -   PETSC_VIEWER_SOCKET_MACHINE - machine name

    289:      Currently the only socket client available is MATLAB. See
    290:      src/dm/tests/ex12.c and ex12.m for an example of usage.

    292:    Notes:
    293:     The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
    294:           use PetscViewerBinaryRead(), PetscViewerBinaryWrite(), PetscViewerBinarWriteStringArray(), PetscViewerBinaryGetDescriptor().

    296:      Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a
    297:      .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD
    298:      for communicating with a MATLAB Engine

    301: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
    302:           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
    303:           PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
    304:           PetscBinaryViewerGetDescriptor(), PetscMatlabEngineCreate()
    305: @*/
    306: PetscErrorCode  PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
    307: {

    311:   PetscViewerCreate(comm,lab);
    312:   PetscViewerSetType(*lab,PETSCVIEWERSOCKET);
    313:   PetscViewerSocketSetConnection(*lab,machine,port);
    314:   return(0);
    315: }

    317: static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscOptionItems *PetscOptionsObject,PetscViewer v)
    318: {
    320:   PetscInt       def = -1;
    321:   char           sdef[256];
    322:   PetscBool      tflg;

    325:   /*
    326:        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
    327:     are listed here for the GUI to display
    328:   */
    329:   PetscOptionsHead(PetscOptionsObject,"Socket PetscViewer Options");
    330:   PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
    331:   if (tflg) {
    332:     PetscOptionsStringToInt(sdef,&def);
    333:   } else def = PETSCSOCKETDEFAULTPORT;
    334:   PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,NULL,NULL);

    336:   PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,NULL,sizeof(sdef),NULL);
    337:   PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",sdef,sizeof(sdef),&tflg);
    338:   if (!tflg) {
    339:     PetscGetHostName(sdef,sizeof(sdef));
    340:   }
    341:   PetscOptionsTail();
    342:   return(0);
    343: }

    345: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Socket(PetscViewer viewer,PetscBool  *skip)
    346: {
    347:   PetscViewer_Socket *vsocket = (PetscViewer_Socket*)viewer->data;

    350:   *skip = vsocket->skipheader;
    351:   return(0);
    352: }

    354: static PetscErrorCode PetscViewerBinarySetSkipHeader_Socket(PetscViewer viewer,PetscBool skip)
    355: {
    356:   PetscViewer_Socket *vsocket = (PetscViewer_Socket*)viewer->data;

    359:   vsocket->skipheader = skip;
    360:   return(0);
    361: }

    363: static PetscErrorCode  PetscViewerBinaryGetFlowControl_Socket(PetscViewer viewer,PetscInt *fc)
    364: {
    366:   *fc = 0;
    367:   return(0);
    368: }

    370: /*MC
    371:    PETSCVIEWERSOCKET - A viewer that writes to a Unix socket

    374: .seealso:  PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSC_VIEWER_DRAW_(),PETSC_VIEWER_DRAW_SELF, PETSC_VIEWER_DRAW_WORLD,
    375:            PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW,
    376:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
    377:            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()

    379:   Level: beginner
    380: M*/

    382: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
    383: {
    384:   PetscViewer_Socket *vmatlab;
    385:   PetscErrorCode     ierr;

    388:   PetscNewLog(v,&vmatlab);
    389:   vmatlab->port          = 0;
    390:   v->data                = (void*)vmatlab;
    391:   v->ops->destroy        = PetscViewerDestroy_Socket;
    392:   v->ops->flush          = NULL;
    393:   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;

    395:   /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
    396:   PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);
    397:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Socket);
    398:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Socket);
    399:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Socket);

    401:   return(0);
    402: }

    404: /*@C
    405:       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
    406:              viewer is to use

    408:   Logically Collective on PetscViewer

    410:   Input Parameters:
    411: +   v - viewer to connect
    412: .   machine - host to connect to, use NULL for the local machine,use "server" to passively wait for
    413:              a connection from elsewhere
    414: -   port - the port on the machine one is connecting to, use PETSC_DEFAULT for default

    416:     Level: advanced

    418: .seealso: PetscViewerSocketOpen()
    419: @*/
    420: PetscErrorCode  PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
    421: {
    422:   PetscErrorCode     ierr;
    423:   PetscMPIInt        rank;
    424:   char               mach[256];
    425:   PetscBool          tflg;
    426:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)v->data;

    430:   if (port <= 0) {
    431:     char portn[16];
    432:     PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
    433:     if (tflg) {
    434:       PetscInt pport;
    435:       PetscOptionsStringToInt(portn,&pport);
    436:       port = (int)pport;
    437:     } else port = PETSCSOCKETDEFAULTPORT;
    438:   }
    439:   if (!machine) {
    440:     PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,sizeof(mach),&tflg);
    441:     if (!tflg) {
    442:       PetscGetHostName(mach,sizeof(mach));
    443:     }
    444:   } else {
    445:     PetscStrncpy(mach,machine,sizeof(mach));
    446:   }

    448:   MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);
    449:   if (!rank) {
    450:     PetscStrcmp(mach,"server",&tflg);
    451:     if (tflg) {
    452:       int listenport;
    453:       PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);
    454:       PetscSocketEstablish(port,&listenport);
    455:       PetscSocketListen(listenport,&vmatlab->port);
    456:       close(listenport);
    457:     } else {
    458:       PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);
    459:       PetscOpenSocket(mach,port,&vmatlab->port);
    460:     }
    461:   }
    462:   return(0);
    463: }

    465: /* ---------------------------------------------------------------------*/
    466: /*
    467:     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
    468:   is attached to a communicator, in this case the attribute is a PetscViewer.
    469: */
    470: PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;

    473: /*@C
    474:      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.

    476:      Collective

    478:      Input Parameter:
    479: .    comm - the MPI communicator to share the socket PetscViewer

    481:      Level: intermediate

    483:    Options Database Keys:
    484:    For use with the default PETSC_VIEWER_SOCKET_WORLD or if
    485:     NULL is passed for machine or PETSC_DEFAULT is passed for port
    486: $    -viewer_socket_machine <machine>
    487: $    -viewer_socket_port <port>

    489:    Environmental variables:
    490: +   PETSC_VIEWER_SOCKET_PORT - portnumber
    491: -   PETSC_VIEWER_SOCKET_MACHINE - machine name

    493:      Notes:
    494:      Unlike almost all other PETSc routines, Petsc_VIEWER_SOCKET_ does not return
    495:      an error code, it returns NULL if it fails. The socket PetscViewer is usually used in the form
    496: $       XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));

    498:      Currently the only socket client available is MATLAB. See
    499:      src/dm/tests/ex12.c and ex12.m for an example of usage.

    501:      Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.

    503:      Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a
    504:      .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD
    505:      for communicating with a MATLAB Engine

    507: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
    508:           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
    509:           PetscViewerBinaryWriteStringArray(), PetscViewerBinaryGetDescriptor(), PETSC_VIEWER_MATLAB_()
    510: @*/
    511: PetscViewer  PETSC_VIEWER_SOCKET_(MPI_Comm comm)
    512: {
    514:   PetscBool      flg;
    515:   PetscViewer    viewer;
    516:   MPI_Comm       ncomm;

    519:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    520:   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
    521:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,NULL);
    522:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    523:   }
    524:   MPI_Comm_get_attr(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg);
    525:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    526:   if (!flg) { /* PetscViewer not yet created */
    527:     PetscViewerSocketOpen(ncomm,NULL,0,&viewer);
    528:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    529:     PetscObjectRegisterDestroy((PetscObject)viewer);
    530:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    531:     MPI_Comm_set_attr(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer);
    532:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    533:   }
    534:   PetscCommDestroy(&ncomm);
    535:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    536:   PetscFunctionReturn(viewer);
    537: }