Open sbinet opened 8 years ago
FYI, it's also present when using a docker
container (centos:7
).
$> xhost +
$> docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
centos:7 bash
docker> yum install -y git gcc && \
curl -O -L https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz && \
tar -C /usr/local -xzf go1.6.linux-amd64.tar.gz
docker> export PATH=/usr/local/go/bin:$PATH
docker> export GOPATH=/go
docker> go get -t -u golang.org/x/exp/shiny/driver/x11driver
docker> cd $GOPATH/src/golang.org/x/exp/shiny/example/basic
docker> go run main.go
XGB: conn.go:47: Could not get authority info: open /root/.Xauthority: no such file or directory
XGB: conn.go:48: Trying connection without authority info...
2016/04/07 12:33:07 x11driver: xproto.WaitForEvent: BadAccess {NiceName: Access, Sequence: 17, BadValue: 83886084, MinorOpcode: 1, MajorOpcode: 130}
2016/04/07 12:33:07 x11driver: xproto.WaitForEvent: BadBadSeg {NiceName: BadSeg, Sequence: 21, BadValue: 83886083, MinorOpcode: 3, MajorOpcode: 130}
@nigeltao any idea?
What is $HOME and $XAUTHORITY for both cases? For docker, it looks like $HOME is "/home", which looks weird. Are you running as root? (Sorry, I'm not very familiar with docker).
On centos, could you strace both the xgb- and xgbutil-based programs and see what files they open, whose names look vaguely like "Xauthority"?
Ah, never mind about the strace. I just read the first post again, and if you can get a window up, then xgb should have auth'd correctly, even if the window isn't painting properly. Hmm...
just a small update. the following program works on centos-7:
package main
import (
"fmt"
"image"
"image/color"
"image/draw"
"time"
"github.com/BurntSushi/xgbutil"
"github.com/BurntSushi/xgbutil/xevent"
"github.com/BurntSushi/xgbutil/xgraphics"
)
func main() {
const (
w = 150
h = 150
)
img := image.NewRGBA(image.Rect(0, 0, int(w), int(h)))
X, err := xgbutil.NewConn()
fatal(err)
ximg := xgraphics.New(X, img.Bounds())
wid := ximg.XShowExtra("foo", true)
go func() {
xevent.Main(X)
}()
ximg.XDraw()
ximg.XPaint(wid.Id)
fmt.Printf("window id: %v\n", wid.Id)
time.Sleep(2 * time.Second)
fmt.Printf("drawing white...\n")
draw.Draw(ximg, ximg.Bounds(), image.NewUniform(color.White), image.Point{0, 0}, draw.Src)
ximg.XDraw()
ximg.XPaint(wid.Id)
time.Sleep(5 * time.Second)
}
func fatal(err error) {
if err != nil {
panic(err)
}
}
I'd still like to know what $HOME and $XAUTHORITY are, and whether you're running as root.
inside the docker container, I get these:
[binet@32e78b70bb07 basic]$ whoami
binet
[binet@32e78b70bb07 basic]$ echo $HOME
/home/binet
[binet@32e78b70bb07 basic]$ echo "auth=[$XAUTHORITY]"
auth=[]
inside a proper centos-7 VM, I am indeed running as root
:
[root@themachine ~]# whoami
root
[root@themachine ~]# echo $HOME
/root
[root@themachine ~]# echo "auth=[$XAUTHORITY]"
auth=[]
and, on another Centos-7 machine I have access to, as a regular user:
13:37 binet@lxplus0099 shiny/example/basic% ./main
2016/04/15 13:37:40 x11driver: xproto.WaitForEvent: BadAccess {NiceName: Access, Sequence: 17, BadValue: 106954756, MinorOpcode: 1, MajorOpcode: 130}
2016/04/15 13:37:40 x11driver: xproto.WaitForEvent: BadBadSeg {NiceName: BadSeg, Sequence: 21, BadValue: 106954755, MinorOpcode: 3, MajorOpcode: 130}
^C
zsh: interrupt ./main
13:37 binet@lxplus0099 shiny/example/basic% echo $HOME
/afs/cern.ch/user/b/binet
13:37 binet@lxplus0099 shiny/example/basic% whoami
binet
13:37 binet@lxplus0099 shiny/example/basic% echo $XAUTHORITY
13:38 binet@lxplus0099 shiny/example/basic% cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
did a bit of print-foo debugging. here are the print-outs:
$ ./main
-- render.Init --
--- case 1: err=<nil> seq=1
----> cookies... (seq=1 err=<nil>)
-- shm.Init --
--- case 1: err=<nil> seq=2
----> cookies... (seq=2 err=<nil>)
-- newScreenImpl --
xsi...
initAtoms...
--- case 1: err=<nil> seq=3
----> cookies... (seq=3 err=<nil>)
--- case 1: err=<nil> seq=4
----> cookies... (seq=4 err=<nil>)
--- case 1: err=<nil> seq=5
----> cookies... (seq=5 err=<nil>)
initKeyboardMapping...
--- case 1: err=<nil> seq=6
----> cookies... (seq=6 err=<nil>)
initPictformats...
--- case 1: err=<nil> seq=7
----> cookies... (seq=7 err=<nil>)
initWindow32...
--- case 1: err=<nil> seq=9
----> cookies... (seq=9 err=<nil>)
s.xsi.Root-Depth = 24 (24)
--- case 1: err=<nil> seq=11
----> cookies... (seq=11 err=<nil>)
--- case 1: err=<nil> seq=13
----> cookies... (seq=13 err=<nil>)
go run()...
... wait for event...
--- case 1: err=<nil> seq=15
----> cookies... (seq=15 err=<nil>)
--- case 1: err=<nil> seq=17
----> cookies... (seq=17 err=<nil>)
--- case 1: err=<nil> seq=19
----> cookies... (seq=19 err=<nil>)
--- case 1: err=<nil> seq=21
----> cookies... (seq=21 err=<nil>)
--- case 1: err=<nil> seq=23
----> cookies... (seq=23 err=<nil>)
--- case default: err=<nil> evtnum=21
--- case 0: err=BadAccess {NiceName: Access, Sequence: 24, BadValue: 111149060, MinorOpcode: 1, MajorOpcode: 130} seq=24
buf=[0 10 24 0 4 0 160 6 1 0 130 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
----> cookies... (seq=24 err=BadAccess {NiceName: Access, Sequence: 24, BadValue: 111149060, MinorOpcode: 1, MajorOpcode: 130})
****cookie err: BadAccess {NiceName: Access, Sequence: 24, BadValue: 111149060, MinorOpcode: 1, MajorOpcode: 130}
... wait for event...
2016/04/15 12:33:55 x11driver: xproto.WaitForEvent: BadAccess {NiceName: Access, Sequence: 24, BadValue: 111149060, MinorOpcode: 1, MajorOpcode: 130}
... wait for event...
--- case default: err=<nil> evtnum=22
... wait for event...
--- case 1: err=<nil> seq=26
----> cookies... (seq=26 err=<nil>)
--- case 1: err=<nil> seq=28
----> cookies... (seq=28 err=<nil>)
--- case default: err=<nil> evtnum=22
... wait for event...
--- case 1: err=<nil> seq=30
----> cookies... (seq=30 err=<nil>)
--- case 0: err=BadBadSeg {NiceName: BadSeg, Sequence: 31, BadValue: 111149059, MinorOpcode: 3, MajorOpcode: 130} seq=31
buf=[0 128 31 0 3 0 160 6 3 0 130 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
----> cookies... (seq=31 err=BadBadSeg {NiceName: BadSeg, Sequence: 31, BadValue: 111149059, MinorOpcode: 3, MajorOpcode: 130})
****cookie err: BadBadSeg {NiceName: BadSeg, Sequence: 31, BadValue: 111149059, MinorOpcode: 3, MajorOpcode: 130}
2016/04/15 12:33:55 x11driver: xproto.WaitForEvent: BadBadSeg {NiceName: BadSeg, Sequence: 31, BadValue: 111149059, MinorOpcode: 3, MajorOpcode: 130}
which correspond to: https://github.com/golang/exp/blob/master/shiny/vendor/github.com/BurntSushi/xgb/xgb.go#L400
buf := make([]byte, 32)
err, seq = nil, 0
if _, err := io.ReadFull(c.conn, buf); err != nil {
Logger.Printf("A read error is unrecoverable: %s", err)
fmt.Printf("**** read error: %v\n", err)
c.eventChan <- err
c.Close()
continue
}
switch buf[0] {
case 0: // This is an error
// Use the constructor function for this error (that is auto
// generated) by looking it up by the error number.
newErrFun, ok := NewErrorFuncs[int(buf[1])]
if !ok {
Logger.Printf("BUG: Could not find error constructor function "+
"for error with number %d.", buf[1])
continue
}
err = newErrFun(buf)
seq = err.SequenceId()
fmt.Printf("--- case 0: err=%v seq=%v\nbuf=%v\n", err, seq, buf)
// This error is either sent to the event channel or a specific
// cookie's error channel below.
case 1: // This is a reply
seq = Get16(buf[2:])
// check to see if this reply has more bytes to be read
size := Get32(buf[4:])
if size > 0 {
byteCount := 32 + size*4
biggerBuf := make([]byte, byteCount)
copy(biggerBuf[:32], buf)
if _, err := io.ReadFull(c.conn, biggerBuf[32:]); err != nil {
Logger.Printf("A read error is unrecoverable: %s", err)
fmt.Printf("**** read-error: %v\n", err)
c.eventChan <- err
c.Close()
continue
}
replyBytes = biggerBuf
} else {
replyBytes = buf
}
fmt.Printf("--- case 1: err=%v seq=%v\n", err, seq)
// This reply is sent to its corresponding cookie below.
default: // This is an event
// Use the constructor function for this event (like for errors,
// and is also auto generated) by looking it up by the event number.
// Note that we AND the event number with 127 so that we ignore
// the most significant bit (which is set when it was sent from
// a SendEvent request).
evNum := int(buf[0] & 127)
newEventFun, ok := NewEventFuncs[evNum]
if !ok {
Logger.Printf("BUG: Could not find event construct function "+
"for event with number %d.", evNum)
fmt.Printf("*** could not find event construct[%d]\n", evNum)
continue
}
fmt.Printf("--- case default: err=%v evtnum=%v\n", err, evNum)
c.eventChan <- newEventFun(buf)
continue
}
fmt.Printf("----> cookies... (seq=%v err=%v)\n", seq, err)
// At this point, we have a sequence number and we're either
// processing an error or a reply, which are both responses to
// requests. So all we have to do is find the cookie corresponding
// to this error/reply, and send the appropriate data to it.
// In doing so, we make sure that any cookies that came before it
// are marked as successful if they are void and checked.
// If there's a cookie that requires a reply that is before this
// reply, then something is wrong.
for cookie := range c.cookieChan {
// This is the cookie we're looking for. Process and break.
if cookie.Sequence == seq {
if err != nil { // this is an error to a request
// synchronous processing
if cookie.errorChan != nil {
fmt.Printf("**** sync-cookie error: %v\n", err)
cookie.errorChan <- err
} else { // asynchronous processing
fmt.Printf("****cookie err: %v\n", err)
c.eventChan <- err
// if this is an unchecked reply, ping the cookie too
if cookie.pingChan != nil {
cookie.pingChan <- true
}
}
} else { // this is a reply
if cookie.replyChan == nil {
Logger.Printf("Reply with sequence id %d does not "+
"have a cookie with a valid reply channel.", seq)
continue
} else {
cookie.replyChan <- replyBytes
}
}
break
}
hth, -s
@sbinet: are you trying to use shiny with a remote display server? The 'afs' in your home path makes me think you are.
@aarzilli dunno. with X11, remote, server and client have (to me) unclear semantics.
in the specific case of the afs
test:
archlinux64b
machine where shiny
is working correctly) I ssh -YC
to lxplus.cern.ch
which is a CentOS-7
machine (and where xlogo
and xclock
are working correctly)hth
for all the variations of (centos-7) machines to which I ssh, the BurntSushi/xgb
examples are working.
the shiny
ones do not.
with X11, server and client have (to me) unclear semantics.
I can sympathize with this.
So, the display server (ie the thing that puts stuff on the screen) you are trying to use is running on your local archlinux64b machine, the shiny program is running on a CentOS-7 machine you are ssh'ing into. This makes the display server "remote" wrt the shiny program.
AFAIK this won't work, x11driver uses MIT-SHM to upload the image and MIT-SHM doesn't work without, you know, actual "shared memory" between the client and the display server.
xgbutil and xgb examples work because they are using server side pixmaps (or whatever they are called, I'm not an expert). I guess it wouldn't be too much work to add PutImage as a fallback for uploading but remember that we're all getting waylanded soon and once we are in wayland-land there's no way remote display servers work.
Change https://golang.org/cl/213199 mentions this issue: shiny/driver/x11driver: failback to regular pixmaps if SHM is unavaiable
Please answer these questions before submitting your issue. Thanks!
go version
)?go env
)?an empty window (with whatever was displayed behind that window, captured into that window but not refreshed) and the following error:
The "interesting" thing is that the pointer-painting example from
xgbutil
works correctly. So it presumably is some configuration issue on thex11driver
end. (I tried replacingxgb.NewConn()
withxgbutil.NewConn()
and adapt a bit, to no avail)