Actual source code: send.c


  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;

 65:   if (vmatlab->port) {
 66: #if defined(PETSC_HAVE_CLOSESOCKET)
 67:     closesocket(vmatlab->port);
 68: #else
 69:     close(vmatlab->port);
 70: #endif
 72:   }
 73:   PetscFree(vmatlab);
 74:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerBinarySetSkipHeader_C", NULL);
 75:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerBinaryGetSkipHeader_C", NULL);
 76:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerBinaryGetFlowControl_C", NULL);
 77:   return 0;
 78: }

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

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

 88:     Output Parameter:
 89: .    t - the socket number

 91:     Notes:
 92:     Use close() to close the socket connection

 94:     Use read() or `PetscHTTPRequest()` to read from the socket

 96:     Level: advanced

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

108:   if (!(hp = gethostbyname(hostname))) {
109:     perror("SEND: error gethostbyname: ");
110:     SETERRQ(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");
120:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "system error");
121:     }
122:     if (connect(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
123: #if defined(PETSC_HAVE_WSAGETLASTERROR)
124:       WSAGetLastError();
125:       if (ierr == WSAEADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n");
126:       else if (ierr == WSAEALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
127:       else if (ierr == WSAEISCONN) {
128:         (*PetscErrorPrintf)("SEND: socket already connected\n");
129:         Sleep((unsigned)1);
130:       } else if (ierr == WSAECONNREFUSED) {
131:         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
132:         Sleep((unsigned)1);
133:       } else {
134:         perror(NULL);
135:         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "system error");
136:       }
137: #else
138:       if (errno == EADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n");
139:       else if (errno == EALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
140:       else if (errno == EISCONN) {
141:         (*PetscErrorPrintf)("SEND: socket already connected\n");
142:         sleep((unsigned)1);
143:       } else if (errno == ECONNREFUSED) {
144:         refcnt++;
146:         PetscInfo(NULL, "Connection refused in attaching socket, trying again\n");
147:         sleep((unsigned)1);
148:       } else {
149:         perror(NULL);
150:         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "system error");
151:       }
152: #endif
153:       flg = PETSC_TRUE;
154: #if defined(PETSC_HAVE_CLOSESOCKET)
155:       closesocket(s);
156: #else
157:       close(s);
158: #endif
159:     } else flg = PETSC_FALSE;
160:   }
161:   *t = s;
162:   return 0;
163: }

165: /*@C
166:    PetscSocketEstablish - starts a listener on a socket

168:    Input Parameters:
169: .    portnumber - the port to wait at

171:    Output Parameters:
172: .     ss - the socket to be used with `PetscSocketListen()`

174:     Level: advanced

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

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

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

190:   hp = gethostbyname(myname);

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

197: #if defined(PETSC_HAVE_SO_REUSEADDR)
198:   {
199:     int optval = 1; /* Turn on the option */
200:     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval));
201:   }
202: #endif

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

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

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

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

229:     Level: advanced

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

242:   /* wait for someone to try to connect */
243:   i = sizeof(struct sockaddr_in);
245:   return 0;
246: }

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

251:    Collective

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:    Options Database Keys:
263:    For use with  `PETSC_VIEWER_SOCKET_WORLD`, `PETSC_VIEWER_SOCKET_SELF`,
264:    `PETSC_VIEWER_SOCKET_()` or if
265:     NULL is passed for machine or PETSC_DEFAULT is passed for port
266: $    -viewer_socket_machine <machine>
267: $    -viewer_socket_port <port>

269:    Environmental variables:
270: +   `PETSC_VIEWER_SOCKET_PORT` - portnumber
271: -   `PETSC_VIEWER_SOCKET_MACHINE` - machine name

273:    Level: intermediate

275:    Notes:
276:    Most users should employ the following commands to access the
277:    MATLAB `PetscViewer`
278: $
279: $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
280: $    MatView(Mat matrix,PetscViewer viewer)
281: $
282: $                or
283: $
284: $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
285: $    VecView(Vec vector,PetscViewer viewer)

287:      Currently the only socket client available is MATLAB, PETSc must be configured with --with-matlab for this client. See
288:      src/dm/tests/ex12.c and ex12.m for an example of usage.

290:     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: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PETSCVIEWERSOCKET`, `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerSetType()`,
298:           `PetscViewerSocketSetConnection()`, `PETSC_VIEWER_SOCKET_`, `PETSC_VIEWER_SOCKET_WORLD`,
299:           `PETSC_VIEWER_SOCKET_SELF`, `PetscViewerBinaryWrite()`, `PetscViewerBinaryRead()`, `PetscViewerBinaryWriteStringArray()`,
300:           `PetscBinaryViewerGetDescriptor()`, `PetscMatlabEngineCreate()`
301: @*/
302: PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm, const char machine[], int port, PetscViewer *lab)
303: {
304:   PetscViewerCreate(comm, lab);
305:   PetscViewerSetType(*lab, PETSCVIEWERSOCKET);
306:   PetscViewerSocketSetConnection(*lab, machine, port);
307:   return 0;
308: }

310: static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v, PetscOptionItems *PetscOptionsObject)
311: {
312:   PetscInt  def = -1;
313:   char      sdef[256];
314:   PetscBool tflg;

316:   /*
317:        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
318:     are listed here for the GUI to display
319:   */
320:   PetscOptionsHeadBegin(PetscOptionsObject, "Socket PetscViewer Options");
321:   PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_PORT", sdef, 16, &tflg);
322:   if (tflg) {
323:     PetscOptionsStringToInt(sdef, &def);
324:   } else def = PETSCSOCKETDEFAULTPORT;
325:   PetscOptionsInt("-viewer_socket_port", "Port number to use for socket", "PetscViewerSocketSetConnection", def, NULL, NULL);

327:   PetscOptionsString("-viewer_socket_machine", "Machine to use for socket", "PetscViewerSocketSetConnection", sdef, NULL, sizeof(sdef), NULL);
328:   PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_MACHINE", sdef, sizeof(sdef), &tflg);
329:   if (!tflg) PetscGetHostName(sdef, sizeof(sdef));
330:   PetscOptionsHeadEnd();
331:   return 0;
332: }

334: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Socket(PetscViewer viewer, PetscBool *skip)
335: {
336:   PetscViewer_Socket *vsocket = (PetscViewer_Socket *)viewer->data;

338:   *skip = vsocket->skipheader;
339:   return 0;
340: }

342: static PetscErrorCode PetscViewerBinarySetSkipHeader_Socket(PetscViewer viewer, PetscBool skip)
343: {
344:   PetscViewer_Socket *vsocket = (PetscViewer_Socket *)viewer->data;

346:   vsocket->skipheader = skip;
347:   return 0;
348: }

350: PETSC_INTERN PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer, PetscInt *);

352: /*MC
353:    PETSCVIEWERSOCKET - A viewer that writes to a Unix socket

355:   Level: beginner

357: .seealso: [](sec_viewers), `PETSC_VIEWERBINARY`, `PetscViewerSocketOpen()`, `PetscViewerDrawOpen()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
358:           `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, `PETSCVIEWERDRAW`,
359:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
360:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
361: M*/

363: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
364: {
365:   PetscViewer_Socket *vmatlab;

367:   PetscNew(&vmatlab);
368:   vmatlab->port          = 0;
369:   vmatlab->flowcontrol   = 256; /* same default as in PetscViewerCreate_Binary() */
370:   v->data                = (void *)vmatlab;
371:   v->ops->destroy        = PetscViewerDestroy_Socket;
372:   v->ops->flush          = NULL;
373:   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;

375:   /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
376:   PetscObjectChangeTypeName((PetscObject)v, PETSCVIEWERBINARY);
377:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", PetscViewerBinarySetSkipHeader_Socket);
378:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", PetscViewerBinaryGetSkipHeader_Socket);
379:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", PetscViewerBinaryGetFlowControl_Binary);

381:   return 0;
382: }

384: /*@C
385:       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
386:              viewer is to use

388:   Logically Collective

390:   Input Parameters:
391: +   v - viewer to connect
392: .   machine - host to connect to, use NULL for the local machine,use "server" to passively wait for
393:              a connection from elsewhere
394: -   port - the port on the machine one is connecting to, use `PETSC_DEFAULT` for default

396:     Level: advanced

398: .seealso: [](sec_viewers), `PETSCVIEWERMATLAB`, `PETSCVIEWERSOCKET`, `PetscViewerSocketOpen()`
399: @*/
400: PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v, const char machine[], int port)
401: {
402:   PetscMPIInt         rank;
403:   char                mach[256];
404:   PetscBool           tflg;
405:   PetscViewer_Socket *vmatlab;

409:   vmatlab = (PetscViewer_Socket *)v->data;
411:   if (port <= 0) {
412:     char portn[16];
413:     PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_PORT", portn, 16, &tflg);
414:     if (tflg) {
415:       PetscInt pport;
416:       PetscOptionsStringToInt(portn, &pport);
417:       port = (int)pport;
418:     } else port = PETSCSOCKETDEFAULTPORT;
419:   }
420:   if (!machine) {
421:     PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_MACHINE", mach, sizeof(mach), &tflg);
422:     if (!tflg) PetscGetHostName(mach, sizeof(mach));
423:   } else {
424:     PetscStrncpy(mach, machine, sizeof(mach));
425:   }

427:   MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank);
428:   if (rank == 0) {
429:     PetscStrcmp(mach, "server", &tflg);
430:     if (tflg) {
431:       int listenport;
432:       PetscInfo(v, "Waiting for connection from socket process on port %d\n", port);
433:       PetscSocketEstablish(port, &listenport);
434:       PetscSocketListen(listenport, &vmatlab->port);
435:       close(listenport);
436:     } else {
437:       PetscInfo(v, "Connecting to socket process on port %d machine %s\n", port, mach);
438:       PetscOpenSocket(mach, port, &vmatlab->port);
439:     }
440:   }
441:   return 0;
442: }

444: /* ---------------------------------------------------------------------*/
445: /*
446:     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
447:   is attached to a communicator, in this case the attribute is a PetscViewer.
448: */
449: PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;

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

454:      Collective

456:      Input Parameter:
457: .    comm - the MPI communicator to share the  `PETSCVIEWERSOCKET` `PetscViewer`

459:      Level: intermediate

461:    Options Database Keys:
462:    For use with the default `PETSC_VIEWER_SOCKET_WORLD` or if
463:     NULL is passed for machine or `PETSC_DEFAULT` is passed for port
464: +    -viewer_socket_machine <machine> - machine to connect to
465: -    -viewer_socket_port <port> - port to connect to

467:    Environmental variables:
468: +   `PETSC_VIEWER_SOCKET_PORT` - portnumber
469: -   `PETSC_VIEWER_SOCKET_MACHINE` - machine name

471:      Notes:
472:      Unlike almost all other PETSc routines, `PETSC_VIEWER_SOCKET_()` does not return
473:      an error code, it returns NULL if it fails. The  `PETSCVIEWERSOCKET`  `PetscViewer` is usually used in the form
474: $       XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));

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

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

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

485: .seealso: [](sec_viewers), `PETSCVIEWERMATLAB`, `PETSCVIEWERSOCKET`, `PETSC_VIEWER_SOCKET_WORLD`, `PETSC_VIEWER_SOCKET_SELF`, `PetscViewerSocketOpen()`, `PetscViewerCreate()`,
486:           `PetscViewerSocketSetConnection()`, `PetscViewerDestroy()`, `PETSC_VIEWER_SOCKET_()`, `PetscViewerBinaryWrite()`, `PetscViewerBinaryRead()`,
487:           `PetscViewerBinaryWriteStringArray()`, `PetscViewerBinaryGetDescriptor()`, `PETSC_VIEWER_MATLAB_()`
488: @*/
489: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
490: {
492:   PetscBool      flg;
493:   PetscViewer    viewer;
494:   MPI_Comm       ncomm;

496:   PetscCommDuplicate(comm, &ncomm, NULL);
497:   if (ierr) {
498:     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
499:     return NULL;
500:   }
501:   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
502:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Socket_keyval, NULL);
503:     if (ierr) {
504:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
505:       return NULL;
506:     }
507:   }
508:   MPI_Comm_get_attr(ncomm, Petsc_Viewer_Socket_keyval, (void **)&viewer, (int *)&flg);
509:   if (ierr) {
510:     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
511:     return NULL;
512:   }
513:   if (!flg) { /* PetscViewer not yet created */
514:     PetscViewerSocketOpen(ncomm, NULL, 0, &viewer);
515:     if (ierr) {
516:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
517:       return NULL;
518:     }
519:     PetscObjectRegisterDestroy((PetscObject)viewer);
520:     if (ierr) {
521:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
522:       return NULL;
523:     }
524:     MPI_Comm_set_attr(ncomm, Petsc_Viewer_Socket_keyval, (void *)viewer);
525:     if (ierr) {
526:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
527:       return NULL;
528:     }
529:   }
530:   PetscCommDestroy(&ncomm);
531:   if (ierr) {
532:     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
533:     return NULL;
534:   }
535:   return viewer;
536: }