Actual source code: send.c

petsc-master 2017-12-13
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: Use close() to close the socket connection

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

 93:     Level: advanced

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

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

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

161: #define MAXHOSTNAME 100
162: /*@C
163:    PetscSocketEstablish - starts a listener on a socket

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

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

171:     Level: advanced

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

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

185:   PetscGetHostName(myname,MAXHOSTNAME);

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

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

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

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

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

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

222:    Input Parameter:
223: .    listenport - obtained with PetscSocketEstablish()

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

228:     Level: advanced

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

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

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

251:    Collective on MPI_Comm

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

259:    Output Parameter:
260: .  lab - a context to use when communicating with the server

262:    Level: intermediate

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

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

283:    Environmental variables:
284: +   PETSC_VIEWER_SOCKET_PORT portnumber
285: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

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

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

297:    Concepts: MATLAB^sending data
298:    Concepts: sockets^sending data

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

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

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

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

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

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

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

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

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

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

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


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

378:   Level: beginner
379: M*/

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

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

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

400:   return(0);
401: }

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

407:   Logically Collective on PetscViewer

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

415:     Level: advanced

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

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

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

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


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

475:      Collective on MPI_Comm

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

480:      Level: intermediate

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

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

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

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

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

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

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

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