Example #1
0
template <class T> T* MemoryChannel<T>::tryReadChannel()
{
  T* tmp;

  static const SIGSELECT sel_mem[] = {1, MEMCHANNEL_SIGNAL};
  union SIGNAL* sig;

  tmp = NULL; /* Default value */

  sig = receive_w_tmo(0, (SIGSELECT*)sel_mem);
  if (sig != NIL){
    if (sig->sigNo == MEMCHANNEL_SIGNAL){
      tmp = (T*)(((struct MemChannelSignal*)sig)->ptr);
    }else{
      assert(1==0);
    }
    free_buf(&sig);    
  }

  return tmp;
}
Example #2
0
int pass_on(ProgramState *s) {
  SIGSELECT sigsel[] = {0,FM_READ_PTR_REPLY};
  union SIGNAL *sig;
  char child_read_buff[BUFSIZ], pipe_read_buff[BUFSIZ];
  struct aiocb child_read_req, pipe_read_req;
  int rfd, wfd = 0;
  FmHandle rfh, child_rfh;
  int outstanding_writes = 0, got_some = 0, child_done = 0;

  if ((rfd = sf_open(s->r_pipe, O_RDONLY, 0)) < 0) {
    ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.\n", s->r_pipe);
    rfd = 0;
    return 1;
  }

  attach(NULL,s->progpid);

  /* Open the log file */
  erts_run_erl_log_open();

  efs_examine_fd(rfd,FLIB_FD_HANDLE,&rfh);
  efs_examine_fd(s->ifd,FLIB_FD_HANDLE,&child_rfh);

  READ_AIO(child_read_req,s->ifd,BUFSIZ,child_read_buff);
  READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);

  while (1) {
    time_t now,last_activity;

    time(&last_activity);
    sig = receive_w_tmo(erts_run_erl_log_alive_minutes()*60000,sigsel);

    time(&now);

    if (sig) {
      erts_run_erl_log_activity(0,now,last_activity);
    } else {
      /* timeout */
      erts_run_erl_log_activity(1,now,last_activity);
      continue;
    }

    switch (sig->signo) {
    case OS_ATTACH_SIG: {
      if (rfd) { sf_close(rfd); rfd = 0; }
      free_buf(&sig);
      child_done = 1;
      /* Make sure to to let all outstanding write request finish */
      if (outstanding_writes)
	break;
      if (wfd) sf_close(wfd);
      return 0;
    }
    case FM_WRITE_PTR_REPLY: {
      if (sig->fm_write_ptr.status == EFS_SUCCESS) {
	if (sig->fm_write_ptr.actual < sig->fm_write_ptr.requested) {
	  WRITE_AIO(wfd, sig->fm_write_ptr.requested-sig->fm_write_ptr.actual,
		    sig->fm_write_ptr.buffer+sig->fm_write_ptr.actual);
	}
      } else {
	/* Assume to_erl has terminated. */
	sf_close(wfd);
	wfd = 0;
      }
      free((char*)sig->fm_write_ptr.buffer);
      aio_dispatch(sig);
      if ((--outstanding_writes == 0) && child_done) {
	if (wfd) sf_close(wfd);
	return 0;
      }
      break;
    }
    case FM_READ_PTR_REPLY: {
      /* Child fd */
      if (sig->fm_read_ptr.handle == child_rfh) {

	/* Child terminated */
	if (sig->fm_read_ptr.status != EFS_SUCCESS ||
	    sig->fm_read_ptr.actual == 0) {

	  if (rfd) { sf_close(rfd); rfd = 0; }

	  if (sig->fm_read_ptr.status != EFS_SUCCESS) {
	    ERROR0(LOG_ERR,"Erlang closed the connection.");
	    aio_dispatch(sig);
	    return 1;
	  }

	  /* child closed connection gracefully */
	  aio_dispatch(sig);
	  if (outstanding_writes) {
	    child_done = 1;
	    break;
	  }

	  if (wfd) sf_close(wfd);

	  return 0;
	} else {
	  erts_run_erl_log_write(sig->fm_read_ptr.buffer,
				 sig->fm_read_ptr.actual);
	  if (wfd) {
	    WRITE_AIO(wfd, sig->fm_read_ptr.actual, sig->fm_read_ptr.buffer);
	    outstanding_writes++;
	  }
	  aio_dispatch(sig);
	  READ_AIO(child_read_req, s->ifd,BUFSIZ, child_read_buff);
	}
      /* pipe fd */
      } else if (sig->fm_read_ptr.handle == rfh) {
	if (sig->fm_read_ptr.status != EFS_SUCCESS) {
	  if(rfd) sf_close(rfd);
	  if(wfd) sf_close(wfd);
	  aio_dispatch(sig);
	  ERRNO_ERR0(LOG_ERR,"Error in reading from FIFO.");
	  return 1;
	}
	if (sig->fm_read_ptr.actual == 0) {
	  /* to_erl closed its end of the pipe */
	  aio_dispatch(sig);
	  sf_close(rfd);
	  rfd = sf_open(s->r_pipe,O_RDONLY|DONT_BLOCK_PLEASE, 0);
	  if (rfd < 0) {
	    ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.",
		       s->r_pipe);
	    rfd = 0;
	  } else {
	    READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);
	  }
	  got_some = 0; /* reset for next session */
	} else {
	  int len = sig->fm_read_ptr.actual;
	  char *buffer = sig->fm_read_ptr.buffer;
	  if (!wfd) {
	    /* Try to open the write pipe to to_erl. Now that we got some data
	     * from to_erl, to_erl should already be reading this pipe - open
	     * should succeed. But in case of error, we just ignore it.
	     */
	    if ((wfd = sf_open(s->w_pipe, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
	      erts_run_erl_log_status("Client expected on FIFO %s, "
				      "but can't open (len=%d)\n",
				      s->w_pipe, sig->fm_read_ptr.actual);
	      sf_close(rfd);
	      rfd = sf_open(s->r_pipe, O_RDONLY|DONT_BLOCK_PLEASE, 0);
	      if (rfd < 0) {
		ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.",
			   s->r_pipe);
		return 1;
	      }
	      wfd = 0;
	    } else {
#ifdef DEBUG
	      erts_run_erl_log_status("run_erl: %s opened for writing\n",
				      s->w_pipe);
#endif
	    }
	  }

	  if (!got_some && wfd && buffer[0] == '\014') {
	    char wbuf[30];
	    int wlen = sn_printf(wbuf,sizeof(wbuf),"[run_erl v%u-%u]\n",
				 RUN_ERL_HI_VER, RUN_ERL_LO_VER);
	    /* For some reason this, the first write aio seems to
	       not get an FM_WRITE_PTR_REPLY, so we do not do:
	       outstanding_writes++;
	    */
	    WRITE_AIO(wfd, wlen, wbuf);
	  }
	  got_some = 1;

	  /* Write the message */
#ifdef DEBUG
	  erts_run_erl_log_status("Pty master write; ");
#endif
	  len = erts_run_erl_extract_ctrl_seq(buffer,len, s->ofd);

	  if (len > 0) {
	    int wlen = erts_run_erl_write_all(s->ofd, buffer, len);
	    if (wlen != len) {
	      aio_dispatch(sig);
	      ERRNO_ERR0(LOG_ERR,"Error in writing to terminal.");
	      if(rfd) sf_close(rfd);
	      if(wfd) sf_close(wfd);
	      return 1;
	    }
	  }
#ifdef DEBUG
	  erts_run_erl_log_status("OK\n");
#endif
	  aio_dispatch(sig);
	  READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);
	}
	}
      break;
    }
    default: {
      free_buf(&sig);
      break;
    }
    }
  }
}