Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: performance issues and doesn't work as expected on Linux wayland-session DE. #66

Open
woshikedayaa opened this issue Oct 31, 2024 · 0 comments

Comments

@woshikedayaa
Copy link

First of all

I want to express my gratitude for developing this package! It has been incredibly helpful in many aspects of my work, and I truly appreciate the time and effort you've invested in it. However, I have noticed some performance issues and unexpected behavior when using it in a Linux Wayland session desktop environment.

Environment

$ cat /etc/os-release
NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
BUILD_ID=rolling
ANSI_COLOR="38;2;23;147;209"
HOME_URL="https://archlinux.org/"
DOCUMENTATION_URL="https://wiki.archlinux.org/"
SUPPORT_URL="https://bbs.archlinux.org/"
BUG_REPORT_URL="https://gitlab.archlinux.org/groups/archlinux/-/issues"
PRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/"
LOGO=archlinux-logo
$ uname -a
Linux arch 6.6.56-1-lts #1 SMP PREEMPT_DYNAMIC Thu, 10 Oct 2024 12:04:53 +0000 x86_64 GNU/Linux

Performance issues

I noticed that each write operation starts a coroutine that then enters a C function

go func() { // serve as a daemon until the ownership is terminated.
		runtime.LockOSThread()
		defer runtime.UnlockOSThread()

		cs := C.CString(s)
		defer C.free(unsafe.Pointer(cs))

		h := cgo.NewHandle(start)
		var ok C.int
		if len(buf) == 0 {
			ok = C.clipboard_write(cs, nil, 0, C.uintptr_t(h))
		} else {
			ok = C.clipboard_write(cs, (*C.uchar)(unsafe.Pointer(&(buf[0]))), C.size_t(len(buf)), C.uintptr_t(h))
		}
		if ok != C.int(0) {
			fmt.Fprintf(os.Stderr, "write failed with status: %d\n", int(ok))
		}
		done <- struct{}{}
		close(done)
	}()

Within the C function clipboard_write, it appears to enter a loop that seems unable to exit (at least, I haven't found an exit condition so far).

// clipboard_write writes the given buf of size n as type typ.
// if start is provided, the value of start will be changed to 1 to indicate
// if the write is availiable for reading.
int clipboard_write(char *typ, unsigned char *buf, size_t n, uintptr_t handle) {
    // ......	
    XEvent event;
    XSelectionRequestEvent* xsr;
    int notified = 0;
    for (;;) { // loop forever
        if (notified == 0) {
            syncStatus(handle, 1); // notify Go side
            notified = 1;
        }
        (*P_XNextEvent)(d, &event);
        switch (event.type) {
        case SelectionClear:
            (*P_XCloseDisplay)(d);
            return 0;
        case SelectionNotify:
            break;
        case SelectionRequest:
            // ......
            if ((R & 2) == 0) (*P_XSendEvent)(d, ev.requestor, 0, 0, (XEvent *)&ev);
            break;
        }
    }
}

I am concerned that repeatedly calling write in this way could lead to performance issues over time. If there’s no performance impact, could you kindly explain why? I would love to understand the mechanics better and learn from your insights.

--

Doesn't Work as Expected on Linux Wayland-session DE

I'm encountering an issue with clipboard operations in a Wayland session on Linux. Here’s a summary of the problem:

// Initialization...
<-clipboard.Write(f, []byte("123456")) // This hangs indefinitely until I manually send a Control-C signal.
//go func() { <-changed }()
return nil

To troubleshoot, I modified the code as follows:

// ...
clipboard.Write(f, []byte("123456"))
return nil

However, this approach doesn’t work as expected—the clipboard doesn’t receive the data successfully. I suspect this is because the Goroutine handling the Write operation doesn't complete before the program exits.

To verify, I added a short delay after Write:

// ...
clipboard.Write(f, []byte("123456"))
time.Sleep(time.Second)
return nil

This works, but introducing an arbitrary sleep is not ideal.

Expected Behavior:
I expected that, after successfully writing to the clipboard, the channel would receive a signal or value indicating completion. This way, I could avoid any delay-based workarounds.

Would you be able to clarify if there’s a preferred way to ensure the Write operation completes before the program exits? Or is there an internal mechanism for confirming successful writes that I might have missed?

@woshikedayaa woshikedayaa changed the title question: performance problem and doesn't work as expected on linux wayland-session DE. Question: performance issues and doesn't work as expected on Linux wayland-session DE. Oct 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant