Exemple #1
0
async def test_ipc_server(tmpdir, monkeypatch):
    # The dummy directory should be automatically created when the server starts
    file1 = Path(tmpdir / "dummy" / "1.lock")
    mut1 = uuid4().hex

    async def _cmd_handler(cmd):
        assert cmd == {"cmd": IPCCommand.FOREGROUND}
        return {"status": "ok"}

    mut1 = uuid4().hex
    async with real_clock_timeout():
        async with run_ipc_server(_cmd_handler,
                                  socket_file=file1,
                                  win32_mutex_name=mut1):

            with pytest.raises(IPCServerAlreadyRunning):
                async with run_ipc_server(_cmd_handler,
                                          socket_file=file1,
                                          win32_mutex_name=mut1):
                    pass

            # Send good command
            ret = await send_to_ipc_server(file1, IPCCommand.FOREGROUND)
            assert ret == {"status": "ok"}

            # Send bad command, should be catched before even trying to reach the server
            with pytest.raises(IPCServerError) as exc:
                ret = await send_to_ipc_server(file1, "dummy")
            assert str(exc.value).startswith("Invalid message format:")

            # Force bad command to reach the server
            monkeypatch.setattr(
                "parsec.core.ipcinterface.cmd_req_serializer.dump",
                lambda x: x)
            with pytest.raises(IPCServerBadResponse) as exc:
                await send_to_ipc_server(file1, "dummy")
            assert exc.value.rep == {
                "status": "invalid_format",
                "reason": "{'cmd': ['Unsupported value: dummy']}",
            }
Exemple #2
0
async def _run_ipc_server(config,
                          main_window,
                          start_arg,
                          task_status=trio.TASK_STATUS_IGNORED):
    new_instance_needed = main_window.new_instance_needed
    foreground_needed = main_window.foreground_needed

    async def _cmd_handler(cmd):
        if cmd["cmd"] == IPCCommand.FOREGROUND:
            foreground_needed.emit()
        elif cmd["cmd"] == IPCCommand.NEW_INSTANCE:
            new_instance_needed.emit(cmd.get("start_arg"))
        return {"status": "ok"}

    # Loop over attemps at running an IPC server or sending the command to an existing one
    while True:

        # Attempt to run an IPC server if Parsec is not already started
        try:
            async with run_ipc_server(
                    _cmd_handler,
                    config.ipc_socket_file,
                    win32_mutex_name=config.ipc_win32_mutex_name):
                task_status.started()
                await trio.sleep_forever()

        # Parsec is already started, give it our work then
        except IPCServerAlreadyRunning:

            # Protect against race conditions, in case the server was shutting down
            try:
                if start_arg:
                    await send_to_ipc_server(config.ipc_socket_file,
                                             IPCCommand.NEW_INSTANCE,
                                             start_arg=start_arg)
                else:
                    await send_to_ipc_server(config.ipc_socket_file,
                                             IPCCommand.FOREGROUND)

            # IPC server has closed, retry to create our own
            except IPCServerNotRunning:
                continue

            # We have successfuly noticed the other running application
            # We can now forward the exception to the caller
            raise
Exemple #3
0
async def _start_ipc_server(config, main_window, start_arg, result_queue):
    new_instance_needed_qt = ThreadSafeQtSignal(main_window,
                                                "new_instance_needed", object)
    foreground_needed_qt = ThreadSafeQtSignal(main_window, "foreground_needed")

    async def cmd_handler(cmd):
        if cmd["cmd"] == "foreground":
            foreground_needed_qt.emit()
        elif cmd["cmd"] == "new_instance":
            new_instance_needed_qt.emit(cmd.get("start_arg"))
        return {"status": "ok"}

    while True:
        try:
            async with run_ipc_server(
                    cmd_handler,
                    config.ipc_socket_file,
                    win32_mutex_name=config.ipc_win32_mutex_name):
                result_queue.put("started")
                await trio.sleep_forever()

        except IPCServerAlreadyRunning:
            # Parsec is already started, give it our work then
            try:
                try:
                    if start_arg:
                        await send_to_ipc_server(config.ipc_socket_file,
                                                 "new_instance",
                                                 start_arg=start_arg)
                    else:
                        await send_to_ipc_server(config.ipc_socket_file,
                                                 "foreground")
                finally:
                    result_queue.put("already_running")
                return

            except IPCServerNotRunning:
                # IPC server has closed, retry to create our own
                continue