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

Windows: Systray: The current process has used all of its system allowance of handles for Window Manager objects #3760

Closed
2 tasks done
d1ss0nanz opened this issue Mar 23, 2023 · 9 comments · Fixed by fyne-io/systray#43
Labels
bug Something isn't working

Comments

@d1ss0nanz
Copy link
Contributor

Checklist

  • I have searched the issue tracker for open issues that relate to the same problem, before opening a new one.
  • This issue only relates to a single bug. I will open new issues for any other problems.

Describe the bug

Systray Menu becomes unresponsive. The following line is logged:
systray error: unable to addOrUpdateMenuItem: The current process has used all of its system allowance of handles for Window Manager objects.

How to reproduce

  1. Build the attached program
  2. ran the resulting exe file
  3. wait a few minutes
  4. the systray menu becomes unresponsive
  5. UserCacheDir/test.log shows the message systray error: unable to addOrUpdateMenuItem: The current process has used all of its system allowance of handles for Window Manager objects.

Screenshots

No response

Example code


import (
	"log"
	"os"
	"strconv"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/driver/desktop"
)

func main() {
	StartLogging("test.log")
	log.Println("starting")
	app := app.New()

	systrayMenu := fyne.NewMenu("Test", &fyne.MenuItem{Label: "Click"})
	if desk, ok := app.(desktop.App); ok {
		desk.SetSystemTrayMenu(systrayMenu)
	}

	systrayMenu.Items = append(systrayMenu.Items, fyne.NewMenuItemSeparator(), &fyne.MenuItem{Label: "a"}, &fyne.MenuItem{Label: "b"}, fyne.NewMenuItemSeparator(), &fyne.MenuItem{Label: "c"})

	log.Println("AddSubMenu")
	AddSubMenu(systrayMenu.Items[0], 1)
	log.Println("AddSubMenu done")

	go func() {
		for {
			time.Sleep(5 * time.Second)
			log.Println("AddSubMenu")
			AddSubMenu(systrayMenu.Items[0], 1)
			log.Println("AddSubMenu done")
			systrayMenu.Refresh()
		}
	}()
	app.Run()
}

func AddSubMenu(parent *fyne.MenuItem, level int) {
	if level > 4 {
		return
	}
	parent.ChildMenu = &fyne.Menu{Label: "Level " + strconv.Itoa(level)}
	menu := parent.ChildMenu
	for i := 0; i < 5; i++ {
		menuItem := &fyne.MenuItem{Label: strconv.Itoa(level) + "." + strconv.Itoa(i), Disabled: false}
		menu.Items = append(menu.Items, menuItem)
		menu.Items = append(menu.Items, fyne.NewMenuItemSeparator())
		AddSubMenu(menuItem, level+1)
	}
}

func StartLogging(logFile string) (*os.File, error) {
	path, _ := os.UserCacheDir()
	_, err := os.Lstat(path)
	if err != nil {
		if os.IsNotExist(err) {
			err = os.MkdirAll(path, 0755)
			if err != nil {
				log.Printf("MkdirAll failed with: %s\n", err.Error())
			}
		} else {
			log.Println(err.Error())
			return nil, err
		}
	}

	filename := path + "/" + logFile
	f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalf("error opening file: %v", err.Error())
	}
	log.SetOutput(f)
	return f, nil
}

Fyne version

2.3.2

Go compiler version

1.20

Operating system and version

Windows 11

Additional Information

No response

@d1ss0nanz d1ss0nanz added the unverified A bug that has been reported but not verified label Mar 23, 2023
@andydotxyz andydotxyz added bug Something isn't working and removed unverified A bug that has been reported but not verified labels Mar 29, 2023
@andydotxyz andydotxyz added this to the Fixes (v2.3.x) milestone Mar 29, 2023
@andydotxyz
Copy link
Member

Confirmed locally

@andydotxyz
Copy link
Member

Looks like the reset of the menu is leaking window handles (as your error rather implied)

If you are able to test then the systray_windows.go file of the systray packge being updated with the following might confirm a potential fix:

func resetMenu() {
	const MF_BYCOMMAND = 0x00000000
	for id, res := range wt.menus {
		_, _, _ := pDeleteMenu.Call(
			uintptr(res),
			uintptr(id),
			MF_BYCOMMAND,
		)
	}
	wt.createMenu()
}

@d1ss0nanz
Copy link
Contributor Author

d1ss0nanz commented Mar 30, 2023

I've add

func resetMenu() {
	const MF_BYCOMMAND = 0x00000000
	for id, res := range wt.menus {
		_, _, _ = pDeleteMenu.Call(
			uintptr(res),
			uintptr(id),
			MF_BYCOMMAND,
		)
	}
	log.Println("systray: resetMenu")
	wt.createMenu()
}

Fixes the system allowance for handles issue.

But still get this after around 5 minutes:

2023/03/30 07:48:24 AddSubMenu
2023/03/30 07:48:24 AddSubMenu done
2023/03/30 07:48:24 systray: resetMenu
2023/03/30 07:48:24 systray error: unable to addOrUpdateMenuItem: The operation completed successfully.
2023/03/30 07:48:24 systray error: unable to addSeparator: The operation completed successfully.
2023/03/30 07:48:24 systray error: unable to addOrUpdateMenuItem: The operation completed successfully.
2023/03/30 07:48:24 systray error: unable to addOrUpdateMenuItem: Invalid menu handle.
2023/03/30 07:48:24 systray error: unable to addSeparator: Invalid menu handle.
2023/03/30 07:48:24 systray error: unable to addOrUpdateMenuItem: Invalid menu handle.
2023/03/30 07:48:24 systray error: unable to addSeparator: Invalid menu handle.
2023/03/30 07:48:24 systray error: unable to addOrUpdateMenuItem: Invalid menu handle.```

And soon after:
```2023/03/30 07:48:24 systray error: unable to addSeparator: Invalid menu handle.
2023/03/30 07:48:24 systray error: unable to addSeparator: The operation completed successfully.
2023/03/30 07:48:24 systray error: unable to addOrUpdateMenuItem: The operation completed successfully.
2023/03/30 07:48:24 systray error: unable to addOrUpdateMenuItem: Not enough memory resources are available to process this command.
2023/03/30 07:48:24 systray error: unable to addSeparator: Invalid menu handle.
2023/03/30 07:48:24 systray error: unable to addOrUpdateMenuItem: Not enough memory resources are available to process this command.
2023/03/30 07:48:24 systray error: unable to addSeparator: Invalid menu handle.
2023/03/30 07:48:24 systray error: unable to addOrUpdateMenuItem: Not enough memory resources are available to process this command.
2023/03/30 07:48:24 systray error: unable to addSeparator: Invalid menu handle.
2023/03/30 07:48:24 systray error: unable to addOrUpdateMenuItem: Not enough memory resources are available to process this command.```

@andydotxyz
Copy link
Member

Thanks, I think maybe it was a too naïve fix. Will dig into it a bit more, perhaps we are leaking multiple handles, or maybe delete needs to be called in a certain way.

@d1ss0nanz
Copy link
Contributor Author

Would using DestroyMenu work?

u32 = windows.NewLazySystemDLL("User32.dll")
var pDestroyMenu = u32.NewProc("DestroyMenu")

func resetMenu() {
	log.Println("systray: resetMenu")
	_, _, _ = pDestroyMenu.Call(uintptr(wt.menus[0]))
	wt.visibleItems = make(map[uint32][]uint32)
	wt.menus = make(map[uint32]windows.Handle)
	wt.menuOf = make(map[uint32]windows.Handle)
	wt.menuItemIcons = make(map[uint32]windows.Handle)
	wt.createMenu()
}

@d1ss0nanz
Copy link
Contributor Author

With the changes above, I can't reproduce any of the issues.

andydotxyz pushed a commit to fyne-io/systray that referenced this issue Apr 3, 2023
@andydotxyz
Copy link
Member

Thanks, can you check out the PR and see if that's correct now?

@d1ss0nanz
Copy link
Contributor Author

Looks good. Can't reproduce the handle issues.

@andydotxyz
Copy link
Member

Thanks for your help, this is now merged on develop

andydotxyz added a commit that referenced this issue Apr 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants