Exemplo n.º 1
0
void session_terminate(session_t *session)
{
    union Key k = { .u64 = session->id };
    qlock(&session_map_mutex);
    mapremove(&session_map, k);
    session->status = SESSION_TERMINATED;
    qunlock(&session_map_mutex);
}

void session_pause(session_t *session, bool pause)
{
    session->status = SESSION_PAUSED;
}

void session_remove_ref(session_t *session)
{
    if (session == NULL) {
        return;
    }
    session_lock(session);
    session->refcount--;
    if (session->refcount == 0 && session->status == SESSION_TERMINATED) {
        if (session->data_cleanup != NULL) {
            session->data_cleanup(session);
        }
        free(session);
        if (chattyv2g) fprintf(stderr, "Succesfully freed session\n");
        // No need to unlock if refcount 0, since it can never increase from this point since it has been removed from the map.
    } else if (session->refcount < 0) {
        if (chattyv2g) fprintf(stderr, "session_remove_ref: Negative session ref-count. THIS IS BAD!\n");
    } else {
        session_unlock(session);
    }
}
Exemplo n.º 2
0
session_t *session_lookup(uint64_t sessionid)
{
    if (sessionid == 0) {
        return NULL;
    }
    union Key k = {.u64 = sessionid};
    qlock(&session_map_mutex);
    session_t **sessionpp =  (session_t**)mapfind(&session_map, k);
    if (sessionpp == NULL) {
        printf("session_lookup: invalid session\n");
        return NULL;
    }
    session_lock(*sessionpp);
    (*sessionpp)->refcount++;
    if ((*sessionpp)->refcount > 4) {
        printf("session_lookup: %d references to the same session, code error is likely\n", (*sessionpp)->refcount);
    }
    session_unlock(*sessionpp);
    qunlock(&session_map_mutex);

    return *sessionpp;
}
Exemplo n.º 3
0
/* This returns vnode with ioref */
static vnode_t
cttyvp(proc_t p)
{
	vnode_t vp;
	int vid;
	struct session *sessp;

	sessp = proc_session(p);

	session_lock(sessp);
	vp = (p->p_flag & P_CONTROLT ? sessp->s_ttyvp : NULLVP);
	vid = sessp->s_ttyvid;	
	session_unlock(sessp);

	session_rele(sessp);

	if (vp != NULLVP) {
		/* cannot get an IO reference, return NULLVP */
		if (vnode_getwithvid(vp, vid) != 0)
			vp = NULLVP;
	}
	return(vp);
}
Exemplo n.º 4
0
// session->mutex must be locked
static int wait_for_playlist_loaded(php_spotify_playlist *playlist) {
	struct timespec ts;
	int err = 0;
	php_spotify_session *session;

	assert(playlist != NULL);
	session = playlist->session;

	DEBUG_PRINT("wait_for_playlist_loaded start\n");

	// Block for a max of SPOTIFY_TIMEOUT seconds
	clock_gettime(CLOCK_REALTIME, &ts);
	ts.tv_sec += SPOTIFY_TIMEOUT;

	request_lock();

	while(err == 0) {
		DEBUG_PRINT("wait_for_playlist_loaded loop\n");
		int loaded;

		session_lock(session);
		loaded = sp_playlist_is_loaded(playlist->playlist);
		session_unlock(session);

		if (loaded)
			break;

		// Wait until a callback is fired
		err = request_sleep_lock(&ts);
	}

	request_unlock();

	DEBUG_PRINT("wait_for_playlist_loaded end(%d)\n", err);
	return err;
}
Exemplo n.º 5
0
/*
 * Device close routine
 */
int
spec_close(struct vnop_close_args *ap)
{
	struct vnode *vp = ap->a_vp;
	dev_t dev = vp->v_rdev;
	int (*devclose)(dev_t, int, int, struct proc *);
	int mode, error;
	int flags = ap->a_fflag;
	struct proc *p = vfs_context_proc(ap->a_context);
	struct session *sessp;

	switch (vp->v_type) {

	case VCHR:
		/*
		 * Hack: a tty device that is a controlling terminal
		 * has a reference from the session structure.
		 * We cannot easily tell that a character device is
		 * a controlling terminal, unless it is the closing
		 * process' controlling terminal.  In that case,
		 * if the reference count is 1 (this is the very
	     * last close)
		 */
		sessp = proc_session(p);
		if (sessp != SESSION_NULL) {
			if ((vcount(vp) == 1) && 
		    		(vp == sessp->s_ttyvp)) {
				session_lock(sessp);
				sessp->s_ttyvp = NULL;
				sessp->s_ttyvid = 0;
				sessp->s_ttyp = TTY_NULL;
				sessp->s_ttypgrpid = NO_PID;
				session_unlock(sessp);
				vnode_rele(vp);
			}
			session_rele(sessp);
		}

		devclose = cdevsw[major(dev)].d_close;
		mode = S_IFCHR;
		/*
		 * close on last reference or on vnode revoke call
		 */
		if ((flags & IO_REVOKE) != 0)
			break;
		if (vcount(vp) > 0)
			return (0);
		break;

	case VBLK:
		/*
		 * Since every use (buffer, vnode, swap, blockmap)
		 * holds a reference to the vnode, and because we mark
		 * any other vnodes that alias this device, when the
		 * sum of the reference counts on all the aliased
		 * vnodes descends to zero, we are on last close.
		 */
		if (vcount(vp) > 0)
			return (0);

		/*
		 * On last close of a block device (that isn't mounted)
		 * we must invalidate any in core blocks, so that
		 * we can, for instance, change floppy disks.
		 */
	        if ((error = spec_fsync_internal(vp, MNT_WAIT, ap->a_context)))
		        return (error);

		error = buf_invalidateblks(vp, BUF_WRITE_DATA, 0, 0);
		if (error)
			return (error);

		devclose = bdevsw[major(dev)].d_close;
		mode = S_IFBLK;
		break;

	default:
		panic("spec_close: not special");
		return(EBADF);
	}

	return ((*devclose)(dev, flags, mode, p));
}
Exemplo n.º 6
0
int
cttyopen(dev_t dev, int flag, __unused int mode, proc_t p)
{
	vnode_t ttyvp = cttyvp(p);
	struct vfs_context context;
	int error = 0;
	int cttyflag, doclose = 0;
	struct session *sessp;

	if (ttyvp == NULL)
		return (ENXIO);

	context.vc_thread = current_thread();
	context.vc_ucred = kauth_cred_proc_ref(p);

	sessp = proc_session(p);
	session_lock(sessp);
	cttyflag = sessp->s_flags & S_CTTYREF;	
	session_unlock(sessp);

	/*
	 * A little hack--this device, used by many processes,
	 * happens to do an open on another device, which can 
	 * cause unhappiness if the second-level open blocks indefinitely 
	 * (as could be the case if the master side has hung up).  Since
	 * we know that this driver doesn't care about the serializing
	 * opens and closes, we can drop the lock. To avoid opencount leak,
	 * open the vnode only for the first time. 
	 */
	if (cttyflag == 0) {
		devsw_unlock(dev, S_IFCHR);
		error = VNOP_OPEN(ttyvp, flag, &context);
		devsw_lock(dev, S_IFCHR);

		if (error) 
			goto out;
	
		/*
		 * If S_CTTYREF is set, some other thread did an open
		 * and was able to set the flag, now perform a close, else
		 * set the flag.
		 */
		session_lock(sessp);
		if (cttyflag == (sessp->s_flags & S_CTTYREF))
			sessp->s_flags |= S_CTTYREF;
		else
			doclose = 1;
		session_unlock(sessp);

		/*
		 * We have to take a reference here to make sure a close
		 * gets called during revoke. Note that once a controlling 
		 * tty gets opened by this driver, the only way close will
		 * get called is when the session leader , whose controlling
		 * tty is ttyvp, exits and vnode is revoked. We cannot 
		 * redirect close from this driver because underlying controlling
		 * terminal might change and close may get redirected to a 
		 * wrong vnode causing panic.
		 */
		if (doclose) {
			devsw_unlock(dev, S_IFCHR);
			VNOP_CLOSE(ttyvp, flag, &context);
			devsw_lock(dev, S_IFCHR);
		} else {
			error = vnode_ref(ttyvp);
		}
	}
out:
	session_rele(sessp);

	vnode_put(ttyvp);
	kauth_cred_unref(&context.vc_ucred);

	return (error);
}