Пример #1
0
static foreign_t
pl_group_info(term_t group, term_t info)
{ int gid;
  struct group grp, *pgrp;
  char buf[1000];
  char *name;
  term_t members = PL_new_term_ref();
  term_t tail = PL_copy_term_ref(members);
  term_t head = PL_new_term_ref();
  char **memp;

  if ( PL_get_integer(group, &gid) )
  { again1:
    errno = 0;
    if ( getgrgid_r(gid, &grp, buf, sizeof(buf), &pgrp) != 0 )
    { if ( errno == EINTR )
      { if ( PL_handle_signals() < 0 )
	  return FALSE;
	goto again1;
      }
      return error(errno, "info", "group", group);
    }
  } else if ( PL_get_chars(group, &name, CVT_ATOMIC|REP_MB) )
  { again2:
    errno = 0;
    if ( getgrnam_r(name, &grp, buf, sizeof(buf), &pgrp) != 0 )
    { if ( errno == EINTR )
      { if ( PL_handle_signals() < 0 )
	  return FALSE;
	goto again2;
      }
      return error(errno, "info", "group", group);
    }
  } else
  { return PL_type_error("group", group);
  }

  if ( !pgrp )
    return PL_existence_error("group", group);

  for(memp=pgrp->gr_mem; *memp; memp++)
  { if ( !PL_unify_list(tail, head, tail) ||
	 !PL_unify_chars(head, PL_ATOM|REP_MB, -1, *memp) )
      return FALSE;
  }
  if ( !PL_unify_nil(tail) )
    return FALSE;

  return PL_unify_term(info,
		       PL_FUNCTOR_CHARS, "group_info", 4,
		         PL_MBCHARS, pgrp->gr_name,
		         PL_MBCHARS, pgrp->gr_passwd,
		         PL_INT, (int)pgrp->gr_gid,
		         PL_TERM, members
		      );
}
Пример #2
0
int
Pause(double t)
{ HANDLE h;

  if ( (h = CreateWaitableTimer(NULL, TRUE, NULL)) )
  { LARGE_INTEGER ft;

    ft.QuadPart = -(LONGLONG)(t * 10000000.0); /* 100 nanosecs per tick */

    SetWaitableTimer(h, &ft, 0, NULL, NULL, FALSE);
    for(;;)
    { int rc = MsgWaitForMultipleObjects(1,
					 &h,
					 FALSE,
					 INFINITE,
					 QS_ALLINPUT);
      if ( rc == WAIT_OBJECT_0+1 )
      { MSG msg;

	while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
	{ TranslateMessage(&msg);
	  DispatchMessage(&msg);
	}

	if ( PL_handle_signals() < 0 )
	{ CloseHandle(h);
	  return FALSE;
	}
      } else
	break;
    }
    CloseHandle(h);

    return TRUE;
  } else				/* Pre NT implementation */
  { DWORD msecs = (DWORD)(t * 1000.0);

    while( msecs >= 100 )
    { Sleep(100);
      if ( PL_handle_signals() < 0 )
	return FALSE;
      msecs -= 100;
    }
    if ( msecs > 0 )
      Sleep(msecs);

    return TRUE;
  }
}
Пример #3
0
int
lockout_readers(rwlock *lock)
{ pthread_mutex_lock(&lock->mutex);

  if ( lock->readers == 0 )
  { ok:

    lock->allow_readers = FALSE;
    pthread_mutex_unlock(&lock->mutex);

    return TRUE;
  }

  lock->waiting_upgrade++;

  for(;;)
  { int rc = pthread_cond_wait(&lock->upcondvar, &lock->mutex);

    if ( rc == EINTR )
    { if ( PL_handle_signals() < 0 )
      { lock->waiting_upgrade--;
	pthread_mutex_unlock(&lock->mutex);
	return FALSE;
      }
      continue;
    } else if ( rc == 0 )
    { if ( lock->readers == 0 )
      { lock->waiting_upgrade--;
	goto ok;
      }
    } else
    { assert(0);			/* TBD: OS errors */
    }
  }
}
Пример #4
0
static int
win32_cond_wait(win32_cond_t *cv,
		CRITICAL_SECTION *external_mutex)
{ int rc;

  cv->waiters++;

  LeaveCriticalSection(external_mutex);
  rc = MsgWaitForMultipleObjects(1,
				 cv->events,
				 FALSE,	/* wait for either event */
				 INFINITE,
				 QS_ALLINPUT);
  if ( rc == WAIT_OBJECT_0+1 )
  { MSG msg;

    while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
    { TranslateMessage(&msg);
      DispatchMessage(&msg);
    }

    if ( PL_handle_signals() < 0 )
    { EnterCriticalSection(external_mutex);
      return WAIT_INTR;
    }
  }

  EnterCriticalSection(external_mutex);

  cv->waiters--;

  return 0;
}
Пример #5
0
static int
wait_success(atom_t name, pid_t pid)
{ pid_t p2;

  for(;;)
  { int status;

    if ( (p2=waitpid(pid, &status, 0)) == pid )
    { if ( WIFEXITED(status) && WEXITSTATUS(status) == 0 )
      { return TRUE;
      } else
      { term_t code, ex;

	if ( (code = PL_new_term_ref()) &&
	     (ex = PL_new_term_ref()) &&
	     unify_exit_status(code, status) &&
	     PL_unify_term(ex,
			   PL_FUNCTOR, FUNCTOR_error2,
			     PL_FUNCTOR, FUNCTOR_process_error2,
			       PL_ATOM, name,
			       PL_TERM, code,
			     PL_VARIABLE) )
	  return PL_raise_exception(ex);
	return FALSE;
      }
    }

    if ( p2 == -1 && errno == EINTR )
    { if ( PL_handle_signals() < 0 )
	return FALSE;
    }
  }
}
Пример #6
0
static int
wait_for_pid(pid_t pid, term_t code, wait_options *opts)
{ pid_t p2;
  int status;

  if ( opts->has_timeout && opts->timeout == 0.0 )
  { if ( (p2=waitpid(pid, &status, WNOHANG)) == pid )
      return unify_exit_status(code, status);
    else if ( p2 == 0 )
      return PL_unify_atom(code, ATOM_timeout);
    else
    { term_t PID;

    error:
      return ((PID = PL_new_term_ref()) &&
	      PL_put_integer(PID, pid) &&
	      pl_error(NULL, 0, "waitpid", ERR_ERRNO,
		       errno, "wait", "process", PID));
    }
  }

  for(;;)
  { if ( (p2=waitpid(pid, &status, 0)) == pid )
      return unify_exit_status(code, status);

    if ( p2 == -1 && errno == EINTR )
    { if ( PL_handle_signals() < 0 )
	return FALSE;
    } else
    { goto error;
    }
  }
}
Пример #7
0
static foreign_t
pl_user_info(term_t user, term_t info)
{ int uid;
  struct passwd pwd, *pwdp;
  char buf[1000];
  char *name;

  if ( PL_get_integer(user, &uid) )
  { again1:
    errno = 0;
    if ( getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwdp) != 0 )
    { if ( errno == EINTR )
      { if ( PL_handle_signals() < 0 )
	  return FALSE;
	goto again1;
      }
      return error(errno, "info", "user", user);
    }
  } else if ( PL_get_chars(user, &name, CVT_ATOMIC|REP_MB) )
  { again2:
    errno = 0;
    if ( getpwnam_r(name, &pwd, buf, sizeof(buf), &pwdp) != 0 )
    { if ( errno == EINTR )
      { if ( PL_handle_signals() < 0 )
	  return FALSE;
	goto again2;
      }
      return error(errno, "info", "user", user);
    }
  } else
  { return PL_type_error("user", user);
  }

  if ( !pwdp )
    return PL_existence_error("user", user);

  return PL_unify_term(info,
		       PL_FUNCTOR_CHARS, "user_info", 7,
		         PL_MBCHARS, pwdp->pw_name,
		         PL_MBCHARS, pwdp->pw_passwd,
		         PL_INT, (int)pwdp->pw_uid,
		         PL_INT, (int)pwdp->pw_gid,
		         PL_MBCHARS, pwdp->pw_gecos,
		         PL_MBCHARS, pwdp->pw_dir,
		         PL_MBCHARS, pwdp->pw_shell
		      );
}
Пример #8
0
static foreign_t
pl_pce_dispatch(void)
{ pceDispatch(-1, 250);

  if ( PL_handle_signals() == -1 || PL_exception(0) )
    return FALSE;

  return TRUE;
}
Пример #9
0
int
wrlock(rwlock *lock, int allow_readers)
{ int self = PL_thread_self();

  if ( lock->writer == self )		/* recursive write lock, used for */
  { lock->lock_level++;			/* nested transactions */

    return TRUE;
  }

  pthread_mutex_lock(&lock->mutex);

  if ( lock->writer == -1 && lock->readers == 0 )
  { ok:

    lock->writer = self;
    lock->lock_level = 1;
    lock->allow_readers = allow_readers;
    pthread_mutex_unlock(&lock->mutex);
    DEBUG(3, Sdprintf("WRLOCK(%d): OK\n", self));

    return TRUE;
  }

  if ( self < lock->thread_max && lock->read_by_thread[self] > 0 )
  { DEBUG(1, Sdprintf("SELF(%d) has %d readers\n",
		      self, lock->read_by_thread[self]));
    pthread_mutex_unlock(&lock->mutex);
    return permission_error("write", "rdf_db", "default",
			    "Operation would deadlock");
  }

  lock->waiting_writers++;
  DEBUG(3, Sdprintf("WRLOCK(%d): waiting ...\n", self));

  for(;;)
  { int rc = pthread_cond_wait(&lock->wrcondvar, &lock->mutex);

    if ( rc == EINTR )
    { if ( PL_handle_signals() < 0 )
      { lock->waiting_writers--;
	pthread_mutex_unlock(&lock->mutex);
	return FALSE;
      }
      continue;
    } else if ( rc == 0 )
    { if ( lock->writer == -1 && lock->readers == 0 )
      { lock->waiting_writers--;
	goto ok;
      }
    } else
    { assert(0);			/* TBD: OS errors */
    }
  }
}
Пример #10
0
static foreign_t
in_pce_thread_sync2(term_t goal, term_t vars)
{ prolog_goal *g = malloc(sizeof(*g));
  MSG msg;
  int rc = FALSE;

  if ( !g )
    return PL_resource_error("memory");

  if ( !init_prolog_goal(g, goal, TRUE) )
  { free(g);
    return FALSE;
  }

  g->client = GetCurrentThreadId();
  PostMessage(context.window, WM_CALL, (WPARAM)0, (LPARAM)g);

  while( GetMessage(&msg, NULL, 0, 0) )
  { TranslateMessage(&msg);
    DispatchMessage(&msg);
    if ( PL_handle_signals() < 0 )
      return FALSE;

    switch(g->state)
    { case G_TRUE:
      { term_t v = PL_new_term_ref();

	rc = PL_recorded(g->result, v) && PL_unify(vars, v);
	PL_erase(g->result);
        goto out;
      }
      case G_FALSE:
	goto out;
      case G_ERROR:
      { term_t ex = PL_new_term_ref();

	if ( PL_recorded(g->result, ex) )
	  rc = PL_raise_exception(ex);
	PL_erase(g->result);
	goto out;
      }
      default:
	continue;
    }
  }

out:
  free(g);
  return rc;
}
Пример #11
0
static int
wait_for_process(process_context *pc)
{ for(;;)
  { int status;
    pid_t p2;

    if ( (p2=waitpid(pc->pid, &status, 0)) == pc->pid )
    { PL_free(pc);
      return TRUE;
    }

    if ( errno == EINTR && PL_handle_signals() >= 0 )
      continue;

    PL_free(pc);
    return FALSE;
  }
}
Пример #12
0
int
rdlock(rwlock *lock)
{ int self = PL_thread_self();

  if ( lock->writer == self )
  { lock->lock_level++;			/* read nested in write */

    return TRUE;
  }

  pthread_mutex_lock(&lock->mutex);

  if ( lock->allow_readers == TRUE )
  { ok:

    lock->readers++;
    register_reader(lock, self);
    pthread_mutex_unlock(&lock->mutex);

    return TRUE;
  }

  lock->waiting_readers++;

  for(;;)
  { int rc = pthread_cond_wait(&lock->rdcondvar, &lock->mutex);

    if ( rc == EINTR )
    { if ( PL_handle_signals() < 0 )
      { lock->waiting_readers--;
	pthread_mutex_unlock(&lock->mutex);
	return FALSE;
      }
      continue;
    } else if ( rc == 0 )
    { if ( lock->allow_readers == TRUE )
      { lock->waiting_readers--;
	goto ok;
      }
    } else
    { assert(0);			/* TBD: OS errors */
    }
  }
}
Пример #13
0
static int
wait_process_handle(HANDLE process, ULONG *rc, DWORD timeout)
{ DWORD wc;

retry:
  wc = MsgWaitForMultipleObjects(1,
				 &process,
				 FALSE,	/* return on any event */
				 timeout,
				 QS_ALLINPUT);

  switch(wc)
  { case WAIT_OBJECT_0:
      if ( !GetExitCodeProcess(process, rc) )
      { win_error("GetExitCodeProcess");
	CloseHandle(process);
	return FALSE;
      }
      CloseHandle(process);
      return TRUE;
    case WAIT_OBJECT_0+1:
    { MSG msg;

      while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
      { TranslateMessage(&msg);
	DispatchMessage(&msg);
	if ( PL_handle_signals() < 0 )
	  return FALSE;
      }
      goto retry;
    }
    case WAIT_TIMEOUT:
      return WP_TIMEOUT;
    default:
      win_error("WaitForSingleObject");
      CloseHandle(process);
      return FALSE;
  }
}
Пример #14
0
static foreign_t
tcp_select(term_t Streams, term_t Available, term_t timeout)
{ fd_set fds;
  struct timeval t, *to;
  double time;
  int n, max = 0, ret, min = 1000000;
  fdentry *map     = NULL;
  term_t head      = PL_new_term_ref();
  term_t streams   = PL_copy_term_ref(Streams);
  term_t available = PL_copy_term_ref(Available);
  term_t ahead     = PL_new_term_ref();
  int from_buffer  = 0;
  atom_t a;

  FD_ZERO(&fds);
  while( PL_get_list(streams, head, streams) )
  { IOSTREAM *s;
#ifdef __WINDOWS__
    nbio_sock_t fd;
#else
    int fd;
#endif
    fdentry *e;

    if ( !PL_get_stream_handle(head, &s) )
      return FALSE;

#ifdef __WINDOWS__
    fd = fdFromHandle(s->handle);
#else
    fd = Sfileno(s);
#endif

    PL_release_stream(s);
    if ( fd < 0 || !is_socket_stream(s) )
    { return pl_error("tcp_select", 3, NULL, ERR_DOMAIN,
		      head, "socket_stream");
    }
					/* check for input in buffer */
    if ( s->bufp < s->limitp )
    { if ( !PL_unify_list(available, ahead, available) ||
	   !PL_unify(ahead, head) )
	return FALSE;
      from_buffer++;
    }

    e         = alloca(sizeof(*e));
    e->fd     = fd;
    e->stream = PL_copy_term_ref(head);
    e->next   = map;
    map       = e;

#ifdef __WINDOWS__
    FD_SET((SOCKET)fd, &fds);
#else
    FD_SET(fd, &fds);
#endif

    if ( fd > max )
      max = fd;
    if( fd < min )
      min = fd;
  }
  if ( !PL_get_nil(streams) )
    return pl_error("tcp_select", 3, NULL, ERR_TYPE, Streams, "list");

  if ( from_buffer > 0 )
    return PL_unify_nil(available);

  if ( PL_get_atom(timeout, &a) && a == ATOM_infinite )
  { to = NULL;
  } else
  { if ( !PL_get_float(timeout, &time) )
      return pl_error("tcp_select", 3, NULL,
		      ERR_TYPE, timeout, "number");

    if ( time >= 0.0 )
    { t.tv_sec  = (int)time;
      t.tv_usec = ((int)(time * 1000000) % 1000000);
    } else
    { t.tv_sec  = 0;
      t.tv_usec = 0;
    }
    to = &t;
  }

  while( (ret=nbio_select(max+1, &fds, NULL, NULL, to)) == -1 &&
	 errno == EINTR )
  { fdentry *e;

    if ( PL_handle_signals() < 0 )
      return FALSE;			/* exception */

    FD_ZERO(&fds);			/* EINTR may leave fds undefined */
    for(e=map; e; e=e->next)		/* so we rebuild it to be safe */
    { FD_SET((SOCKET)e->fd, &fds);
    }
  }

  switch(ret)
  { case -1:
      return pl_error("tcp_select", 3, NULL, ERR_ERRNO, errno, "select", "streams", Streams);

    case 0: /* Timeout */
      break;

    default: /* Something happened -> check fds */
      for(n=min; n <= max; n++)
      { if ( FD_ISSET(n, &fds) )
	{ if ( !PL_unify_list(available, ahead, available) ||
	       !PL_unify(ahead, findmap(map, n)) )
	    return FALSE;
	}
      }
      break;
  }

  return PL_unify_nil(available);
}
Пример #15
0
/** polling loop til buffer ready
 */
ssize_t Swipl_IO::_read_(char *buf, size_t bufsize) {

    qDebug() << "_read_" << CVP(target);
    int thid = PL_thread_self();

    // handle setup interthread and termination
    for ( ; ; ) {
        {   QMutexLocker lk(&sync);
            if (target) {
                if (!target->thids.contains(thid)) {
                    target->add_thread(thid);
                    int rc =
                    PL_thread_at_exit(eng_at_exit, this, FALSE);
                    qDebug() << "installed" << rc;
                }
                break;
            }
        }

	if ( PL_handle_signals() < 0 )
	    return -1;

        SwiPrologEngine::msleep(10);
    }

    if ( buffer.isEmpty() ) {
        PL_write_prompt(TRUE);
	emit user_prompt(thid, SwiPrologEngine::is_tty(this));
    }

    for ( ; ; ) {

        {   QMutexLocker lk(&sync);

            if (!query.isEmpty()) {
                try {
                    int rc = PlCall(query.toStdWString().data());
                    qDebug() << "PlCall" << query << rc;
                }
                catch(PlException e) {
                    qDebug() << t2w(e);
                }
                query.clear();
            }

            uint n = buffer.length();
            Q_ASSERT(bufsize >= n);
            if (n > 0) {
                uint l = bufsize < n ? bufsize : n;
                memcpy(buf, buffer, l);
                buffer.remove(0, l);
                return l;
            }

            if (target->status == ConsoleEdit::eof) {
	        target->status = ConsoleEdit::running;
                return 0;
	    }
        }

	if ( PL_handle_signals() < 0 )
	    return -1;

        SwiPrologEngine::msleep(10);
    }
}
Пример #16
0
static foreign_t
in_pce_thread_sync2(term_t goal, term_t vars)
{ prolog_goal *g;
  int rc;

  if ( !setup() )
    return FALSE;

  if ( !(g  = malloc(sizeof(*g))) )
    return PL_resource_error("memory");

  if ( !init_prolog_goal(g, goal, TRUE) )
    return FALSE;

  pthread_cond_init(&g->cv, NULL);
  pthread_mutex_init(&g->mutex, NULL);
  rc = write(context.pipe[1], &g, sizeof(g));

  if ( rc == sizeof(g) )
  { rc = FALSE;
    pthread_mutex_lock(&g->mutex);

    for(;;)
    { struct timespec timeout;
#ifdef HAVE_CLOCK_GETTIME
      struct timespec now;

      clock_gettime(CLOCK_REALTIME, &now);
      timeout.tv_sec  = now.tv_sec;
      timeout.tv_nsec = (now.tv_nsec+250000000);
#else
      struct timeval now;

      gettimeofday(&now, NULL);
      timeout.tv_sec  = now.tv_sec;
      timeout.tv_nsec = (now.tv_usec+250000) * 1000;
#endif

      if ( timeout.tv_nsec >= 1000000000 ) /* some platforms demand this */
      { timeout.tv_nsec -= 1000000000;
	timeout.tv_sec += 1;
      }

      pthread_cond_timedwait(&g->cv, &g->mutex, &timeout);
      if ( PL_handle_signals() < 0 )
	goto out;

      switch(g->state)
      { case G_TRUE:
	{ term_t v = PL_new_term_ref();

	  rc = PL_recorded(g->result, v) && PL_unify(vars, v);
	  PL_erase(g->result);
	  goto out;
	}
	case G_FALSE:
	  goto out;
	case G_ERROR:
	{ term_t ex = PL_new_term_ref();

	  if ( PL_recorded(g->result, ex) )
	    rc = PL_raise_exception(ex);
	  PL_erase(g->result);
	  goto out;
	}
	default:
	  continue;
      }
    }
  out:
    pthread_mutex_unlock(&g->mutex);
  }

  pthread_mutex_destroy(&g->mutex);
  pthread_cond_destroy(&g->cv);
  free(g);

  return rc;
}