Repository: PistonDevelopers/glfw-rs (language: rust)

Issue:
All examples exit crashes immediately due to segmentation fault.
➜  examples git:(master) rustc -v
rustc 0.10-pre (c80d28c 2014-02-01 00:46:23 -0800)
host: i686-unknown-linux-gnu



Discussion / hints:
Now this is very odd. They seem to work fine here, on x86_64-apple-darwin with the latest rustc. Is anybody else on linux having issues?

I just updated both rust and glfw-rs to the most recent on github and the examples work fine.

$ rustc -v
rustc 0.10-pre (2bcd951 2014-02-01 11:16:24 -0800)
host: x86_64-unknown-linux-gnu

I wish I could offer further help, but I have zero knowledge of gdb.

> I wish I could offer further help, but I have zero knowledge of gdb.

Thanks for your help anyway!

@Pranz Is this still an issue for you?

All examples except version and modes segfault on my machine as well.

glfw-rs 4be8a27

Debian 7.3
Linux 3.2.0-4-686-pae
EGLIBC 2.13-38
rustc 0.10-pre (58985e1)

```
gdb examples/window 
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from window...done.
(gdb) run
Starting program: window 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/i686/cmov/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x08226450 in _GLOBAL_OFFSET_TABLE_ ()
(gdb) bt
#0  0x08226450 in _GLOBAL_OFFSET_TABLE_ ()
#1  0x0804f84f in callbacks::set_error_callback::h33de3c7f69b2f696aN::v0.0 ()
#2  0x0804f772 in set_error_callback::hb15f0fac2f7b8ec5aH::v0.0 ()
#3  0x0804f6a0 in main::h68c3a44b326bcba9aA::v0.0 ()
#4  0x0804f700 in main::as_closure::aE ()
#5  0x0817be09 in run::hfc9910487037c346aY::v0.10.pre ()
#6  0x0817bd7a in start::anon::expr_fn::az ()
#7  0x080ed569 in rt::task::__extensions__::run::anon::expr_fn::aj ()
#8  0x080f1c64 in rt::unwind::Unwinder::try::try_fn::hd22e568e8fb43a5dq2ac::v0.10.pre ()
#9  0x080f5143 in rust_try ()
#10 0x080ed4cc in rt::task::Task::run::hd41110955277f10c7tag::v0.10.pre ()
#11 0x0817bc60 in start::haa0defaded2b076cab::v0.10.pre ()
#12 0x0804f5eb in start::h19c4b6be8e2b1427ah::v0.0 ()
#13 0x0804f63f in main ()
```

Hmm, any clue about this @cmr?

segv in the GOT? that's really weird. I think it might be segfaulting trying to write to the static mut. @ursic can you get a disassembly of frames 0, 1, and 2?

```
(gdb) frame 0
#0  0x08226450 in _GLOBAL_OFFSET_TABLE_ ()
(gdb) disassemble 
Dump of assembler code for function _GLOBAL_OFFSET_TABLE_:
=> 0x08226450 <+0>:     pop    %eax
   0x08226451 <+1>:     popa   
   0x08226452 <+2>:     and    (%eax),%cl
   0x08226454 <+4>:     or     %bh,%cl
   0x08226456 <+6>:     pushl  -0x4800a650(%edi)
End of assembler dump.


(gdb) frame 1
#1  0x0804f84f in callbacks::set_error_callback::h33de3c7f69b2f696aN::v0.0 ()
(gdb) disassemble
Dump of assembler code for function _ZN9callbacks18set_error_callback19h33de3c7f69b2f696aN4v0.0E:
   0x0804f7c0 <+0>:     cmp    %gs:0x30,%esp
   0x0804f7c7 <+7>:     ja     0x804f7d9 <_ZN9callbacks18set_error_callback19h33de3c7f69b2f696aN4v0.0E+25>
   0x0804f7c9 <+9>:     push   $0x8
   0x0804f7ce <+14>:    push   $0x3c
   0x0804f7d3 <+19>:    call   0x819c3a4 <__morestack>
   0x0804f7d8 <+24>:    ret    
   0x0804f7d9 <+25>:    push   %ebx
   0x0804f7da <+26>:    push   %edi
   0x0804f7db <+27>:    push   %esi
   0x0804f7dc <+28>:    sub    $0x30,%esp
   0x0804f7df <+31>:    call   0x804f7e4 <_ZN9callbacks18set_error_callback19h33de3c7f69b2f696aN4v0.0E+36>
   0x0804f7e4 <+36>:    pop    %eax
   0x0804f7e5 <+37>:    add    $0x1d6c6c,%eax
   0x0804f7eb <+43>:    mov    0x44(%esp),%ecx
   0x0804f7ef <+47>:    mov    0x40(%esp),%edx
   0x0804f7f3 <+51>:    mov    %edx,0x2c(%esp)
   0x0804f7f7 <+55>:    mov    -0x1c(%eax),%esi
   0x0804f7fd <+61>:    mov    (%esi),%esi
   0x0804f7ff <+63>:    mov    %edx,0x24(%esp)
   0x0804f803 <+67>:    movl   $0x0,0x2c(%esp)
   0x0804f80b <+75>:    lea    -0x16ef8(%eax),%edx
   0x0804f811 <+81>:    mov    %edx,0x20(%esp)
   0x0804f815 <+85>:    mov    %esp,%edx
   0x0804f817 <+87>:    lea    0x20(%esp),%edi
   0x0804f81b <+91>:    mov    %edi,0x4(%edx)
   0x0804f81e <+94>:    mov    %esi,(%edx)
   0x0804f820 <+96>:    mov    %eax,%ebx
   0x0804f822 <+98>:    mov    %eax,0x14(%esp)
   0x0804f826 <+102>:   mov    %ecx,0x10(%esp)
   0x0804f82a <+106>:   call   0x804f8a0 <_ZN10local_data3set19h732b292f64c0c5e8a04v0.0E>
   0x0804f82f <+111>:   jmp    0x804f831 <_ZN9callbacks18set_error_callback19h33de3c7f69b2f696aN4v0.0E+113>
   0x0804f831 <+113>:   mov    0x10(%esp),%eax
   0x0804f835 <+117>:   mov    (%eax),%ecx
   0x0804f837 <+119>:   mov    0x4(%eax),%edx
   0x0804f83a <+122>:   mov    0x14(%esp),%esi
   0x0804f83e <+126>:   mov    -0x58(%esi),%edi
   0x0804f844 <+132>:   mov    %esp,%ebx
   0x0804f846 <+134>:   mov    %edi,0x4(%ebx)
   0x0804f849 <+137>:   mov    %edx,(%ebx)
   0x0804f84b <+139>:   mov    %esi,%ebx
   0x0804f84d <+141>:   call   *%ecx
=> 0x0804f84f <+143>:   jmp    0x804f885 <_ZN9callbacks18set_error_callback19h33de3c7f69b2f696aN4v0.0E+197>
   0x0804f851 <+145>:   mov    %edx,0x1c(%esp)
   0x0804f855 <+149>:   mov    %eax,0x18(%esp)
   0x0804f859 <+153>:   jmp    0x804f873 <_ZN9callbacks18set_error_callback19h33de3c7f69b2f696aN4v0.0E+179>
   0x0804f85b <+155>:   mov    0x18(%esp),%eax
   0x0804f85f <+159>:   mov    0x1c(%esp),%ecx
   0x0804f863 <+163>:   mov    %eax,(%esp)
   0x0804f866 <+166>:   mov    0x14(%esp),%ebx
   0x0804f86a <+170>:   mov    %ecx,0xc(%esp)
   0x0804f86e <+174>:   call   0x804f270 <_Unwind_Resume@plt>
   0x0804f873 <+179>:   lea    0x2c(%esp),%eax
   0x0804f877 <+183>:   mov    %eax,(%esp)
   0x0804f87a <+186>:   mov    0x14(%esp),%ebx
   0x0804f87e <+190>:   call   0x8051f10 <_ZN2i89glue_drop19h286b78cda8ddae8eaQE>
   0x0804f883 <+195>:   jmp    0x804f85b <_ZN9callbacks18set_error_callback19h33de3c7f69b2f696aN4v0.0E+155>
   0x0804f885 <+197>:   lea    0x2c(%esp),%eax
   0x0804f889 <+201>:   mov    %eax,(%esp)
   0x0804f88c <+204>:   mov    0x14(%esp),%ebx
   0x0804f890 <+208>:   call   0x8051f10 <_ZN2i89glue_drop19h286b78cda8ddae8eaQE>
   0x0804f895 <+213>:   add    $0x30,%esp
   0x0804f898 <+216>:   pop    %esi
   0x0804f899 <+217>:   pop    %edi
   0x0804f89a <+218>:   pop    %ebx
   0x0804f89b <+219>:   ret    
End of assembler dump.


(gdb) frame 2
#2  0x0804f772 in set_error_callback::hb15f0fac2f7b8ec5aH::v0.0 ()
(gdb) disassemble 
Dump of assembler code for function _ZN18set_error_callback19hb15f0fac2f7b8ec5aH4v0.0E:
   0x0804f710 <+0>:     cmp    %gs:0x30,%esp
   0x0804f717 <+7>:     ja     0x804f729 <_ZN18set_error_callback19hb15f0fac2f7b8ec5aH4v0.0E+25>
   0x0804f719 <+9>:     push   $0x4
   0x0804f71e <+14>:    push   $0x2c
   0x0804f723 <+19>:    call   0x819c3a4 <__morestack>
   0x0804f728 <+24>:    ret    
   0x0804f729 <+25>:    push   %ebx
   0x0804f72a <+26>:    push   %esi
   0x0804f72b <+27>:    sub    $0x24,%esp
   0x0804f72e <+30>:    call   0x804f733 <_ZN18set_error_callback19hb15f0fac2f7b8ec5aH4v0.0E+35>
   0x0804f733 <+35>:    pop    %eax
   0x0804f734 <+36>:    add    $0x1d6d1d,%eax
   0x0804f73a <+42>:    mov    0x30(%esp),%ecx
   0x0804f73e <+46>:    mov    %ecx,0x20(%esp)
   0x0804f742 <+50>:    movl   $0x0,0x20(%esp)
   0x0804f74a <+58>:    lea    -0x1d4520(%eax),%edx
   0x0804f750 <+64>:    mov    %edx,0x18(%esp)
   0x0804f754 <+68>:    movl   $0x0,0x1c(%esp)
   0x0804f75c <+76>:    mov    %esp,%edx
   0x0804f75e <+78>:    lea    0x18(%esp),%esi
   0x0804f762 <+82>:    mov    %esi,0x4(%edx)
   0x0804f765 <+85>:    mov    %ecx,(%edx)
   0x0804f767 <+87>:    mov    %eax,%ebx
   0x0804f769 <+89>:    mov    %eax,0xc(%esp)
   0x0804f76d <+93>:    call   0x804f7c0 <_ZN9callbacks18set_error_callback19h33de3c7f69b2f696aN4v0.0E>
=> 0x0804f772 <+98>:    jmp    0x804f774 <_ZN18set_error_callback19hb15f0fac2f7b8ec5aH4v0.0E+100>
   0x0804f774 <+100>:   lea    0x20(%esp),%eax
   0x0804f778 <+104>:   mov    %eax,(%esp)
   0x0804f77b <+107>:   mov    0xc(%esp),%ebx
   0x0804f77f <+111>:   call   0x8051f10 <_ZN2i89glue_drop19h286b78cda8ddae8eaQE>
   0x0804f784 <+116>:   add    $0x24,%esp
   0x0804f787 <+119>:   pop    %esi
   0x0804f788 <+120>:   pop    %ebx
   0x0804f789 <+121>:   ret    
   0x0804f78a <+122>:   mov    %edx,0x14(%esp)
   0x0804f78e <+126>:   mov    %eax,0x10(%esp)
   0x0804f792 <+130>:   jmp    0x804f7ac <_ZN18set_error_callback19hb15f0fac2f7b8ec5aH4v0.0E+156>
   0x0804f794 <+132>:   mov    0x10(%esp),%eax
   0x0804f798 <+136>:   mov    0x14(%esp),%ecx
   0x0804f79c <+140>:   mov    %eax,(%esp)
   0x0804f79f <+143>:   mov    0xc(%esp),%ebx
   0x0804f7a3 <+147>:   mov    %ecx,0x8(%esp)
   0x0804f7a7 <+151>:   call   0x804f270 <_Unwind_Resume@plt>
   0x0804f7ac <+156>:   lea    0x20(%esp),%eax
   0x0804f7b0 <+160>:   mov    %eax,(%esp)
   0x0804f7b3 <+163>:   mov    0xc(%esp),%ebx
   0x0804f7b7 <+167>:   call   0x8051f10 <_ZN2i89glue_drop19h286b78cda8ddae8eaQE>
   0x0804f7bc <+172>:   jmp    0x804f794 <_ZN18set_error_callback19hb15f0fac2f7b8ec5aH4v0.0E+132>
End of assembler dump.
```

Are you guys on 32-bit systems?

Yes, I thought 3.2.0-4-686-pae already said so.

I think this is the same problem I saw in bjz/glfw-rs#67. I checked out bjz/glfw-rs master and reproduced the segfault with the same backtrace. I'm also running 32-bit Linux.

@ursic Can you try rlane/glfw-rs branch gamedev-kit? It has a workaround.

Ah bugger. It _still_ hasn't been fixed? :(

@rlane that works.


Fix patch:
diff --git a/src/lib/callbacks.rs b/src/lib/callbacks.rs
index f51da59f..2c161e6c 100644
--- a/src/lib/callbacks.rs
+++ b/src/lib/callbacks.rs
@@ -41,15 +41,29 @@ macro_rules! callback(
             }
         }
 
+        #[cfg(not(target_word_size = "32"))]
         pub fn set<UserData: 'static>(f: ::$Callback<UserData>) {
             ::std::local_data::set(CALLBACK_KEY, ~f as ~Object<Args>:'static);
             ($ext_set)(Some(callback));
         }
+        // FIXME: workaround for mozilla/rust#11040
+        #[cfg(target_word_size = "32")]
+        pub fn set<UserData: 'static>(f: ::$Callback<UserData>) {
+            ::std::local_data::set(CALLBACK_KEY, ~f as ~Object<Args>:'static);
+            ($ext_set)(callback);
+        }
 
+        #[cfg(not(target_word_size = "32"))]
         pub fn unset() {
             ::std::local_data::pop(CALLBACK_KEY);
             ($ext_set)(None);
         }
+        // FIXME: workaround for mozilla/rust#11040
+        #[cfg(target_word_size = "32")]
+        pub fn unset() {
+            ::std::local_data::pop(CALLBACK_KEY);
+            ($ext_set)(unsafe { cast::transmute(::std::ptr::null::<::libc::c_void>()) });
+        }
 
         extern "C" fn callback($($ext_arg: $ext_arg_ty),*) {
             ::std::local_data::get(CALLBACK_KEY, |data| {
diff --git a/src/lib/ffi.rs b/src/lib/ffi.rs
index da8f0e9c..bffc0b8d 100644
--- a/src/lib/ffi.rs
+++ b/src/lib/ffi.rs
@@ -294,14 +294,18 @@ extern "C" {
     pub fn glfwGetVersion(major: *mut c_int, minor: *mut c_int, rev: *mut c_int);
     pub fn glfwGetVersionString() -> *c_char;
 
-    pub fn glfwSetErrorCallback(cbfun: Option<GLFWerrorfun>) -> Option<GLFWerrorfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetErrorCallback(cbfun: Option<GLFWerrorfun>) -> Option<GLFWerrorfun>;
+    // FIXME: workaround for mozilla/rust#11040
+    #[cfg(target_word_size = "32")] pub fn glfwSetErrorCallback(cbfun: GLFWerrorfun) -> GLFWerrorfun;
 
     pub fn glfwGetMonitors(count: *mut c_int) -> **GLFWmonitor;
     pub fn glfwGetPrimaryMonitor() -> *GLFWmonitor;
     pub fn glfwGetMonitorPos(monitor: *GLFWmonitor, xpos: *mut c_int, ypos: *mut c_int);
     pub fn glfwGetMonitorPhysicalSize(monitor: *GLFWmonitor, width: *mut c_int, height: *mut c_int);
     pub fn glfwGetMonitorName(monitor: *GLFWmonitor) -> *c_char;
-    pub fn glfwSetMonitorCallback(cbfun: Option<GLFWmonitorfun>) -> Option<GLFWmonitorfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetMonitorCallback(cbfun: Option<GLFWmonitorfun>) -> Option<GLFWmonitorfun>;
+    // FIXME: workaround for mozilla/rust#11040
+    #[cfg(target_word_size = "32")] pub fn glfwSetMonitorCallback(cbfun: GLFWmonitorfun) -> GLFWmonitorfun;
     pub fn glfwGetVideoModes(monitor: *GLFWmonitor, count: *mut c_int) -> *GLFWvidmode;
     pub fn glfwGetVideoMode(monitor: *GLFWmonitor) -> *GLFWvidmode;
     pub fn glfwSetGamma(monitor: *GLFWmonitor, gamma: c_float);
@@ -328,13 +332,21 @@ extern "C" {
     pub fn glfwGetWindowAttrib(window: *GLFWwindow, attrib: c_int) -> c_int;
     pub fn glfwSetWindowUserPointer(window: *GLFWwindow, pointer: *c_void);
     pub fn glfwGetWindowUserPointer(window: *GLFWwindow) -> *c_void;
-    pub fn glfwSetWindowPosCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowposfun>) -> Option<GLFWwindowposfun>;
-    pub fn glfwSetWindowSizeCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowsizefun>) -> Option<GLFWwindowsizefun>;
-    pub fn glfwSetWindowCloseCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowclosefun>) -> Option<GLFWwindowclosefun>;
-    pub fn glfwSetWindowRefreshCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowrefreshfun>) -> Option<GLFWwindowrefreshfun>;
-    pub fn glfwSetWindowFocusCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowfocusfun>) -> Option<GLFWwindowfocusfun>;
-    pub fn glfwSetWindowIconifyCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowiconifyfun>) -> Option<GLFWwindowiconifyfun>;
-    pub fn glfwSetFramebufferSizeCallback(window: *GLFWwindow, cbfun: Option<GLFWframebuffersizefun>) -> Option<GLFWframebuffersizefun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetWindowPosCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowposfun>) -> Option<GLFWwindowposfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetWindowSizeCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowsizefun>) -> Option<GLFWwindowsizefun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetWindowCloseCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowclosefun>) -> Option<GLFWwindowclosefun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetWindowRefreshCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowrefreshfun>) -> Option<GLFWwindowrefreshfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetWindowFocusCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowfocusfun>) -> Option<GLFWwindowfocusfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetWindowIconifyCallback(window: *GLFWwindow, cbfun: Option<GLFWwindowiconifyfun>) -> Option<GLFWwindowiconifyfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetFramebufferSizeCallback(window: *GLFWwindow, cbfun: Option<GLFWframebuffersizefun>) -> Option<GLFWframebuffersizefun>;
+    // FIXME: workaround for mozilla/rust#11040
+    #[cfg(target_word_size = "32")] pub fn glfwSetWindowPosCallback(window: *GLFWwindow, cbfun: GLFWwindowposfun) -> GLFWwindowposfun;
+    #[cfg(target_word_size = "32")] pub fn glfwSetWindowSizeCallback(window: *GLFWwindow, cbfun: GLFWwindowsizefun) -> GLFWwindowsizefun;
+    #[cfg(target_word_size = "32")] pub fn glfwSetWindowCloseCallback(window: *GLFWwindow, cbfun: GLFWwindowclosefun) -> GLFWwindowclosefun;
+    #[cfg(target_word_size = "32")] pub fn glfwSetWindowRefreshCallback(window: *GLFWwindow, cbfun: GLFWwindowrefreshfun) -> GLFWwindowrefreshfun;
+    #[cfg(target_word_size = "32")] pub fn glfwSetWindowFocusCallback(window: *GLFWwindow, cbfun: GLFWwindowfocusfun) -> GLFWwindowfocusfun;
+    #[cfg(target_word_size = "32")] pub fn glfwSetWindowIconifyCallback(window: *GLFWwindow, cbfun: GLFWwindowiconifyfun) -> GLFWwindowiconifyfun;
+    #[cfg(target_word_size = "32")] pub fn glfwSetFramebufferSizeCallback(window: *GLFWwindow, cbfun: GLFWframebuffersizefun) -> GLFWframebuffersizefun;
 
     pub fn glfwPollEvents();
     pub fn glfwWaitEvents();
@@ -345,12 +357,19 @@ extern "C" {
     pub fn glfwGetMouseButton(window: *GLFWwindow, button: c_int) -> c_int;
     pub fn glfwGetCursorPos(window: *GLFWwindow, xpos: *mut c_double, ypos: *mut c_double);
     pub fn glfwSetCursorPos(window: *GLFWwindow, xpos: c_double, ypos: c_double);
-    pub fn glfwSetKeyCallback(window: *GLFWwindow, cbfun: Option<GLFWkeyfun>) -> Option<GLFWkeyfun>;
-    pub fn glfwSetCharCallback(window: *GLFWwindow, cbfun: Option<GLFWcharfun>) -> Option<GLFWcharfun>;
-    pub fn glfwSetMouseButtonCallback(window: *GLFWwindow, cbfun: Option<GLFWmousebuttonfun>) -> Option<GLFWmousebuttonfun>;
-    pub fn glfwSetCursorPosCallback(window: *GLFWwindow, cbfun: Option<GLFWcursorposfun>) -> Option<GLFWcursorposfun>;
-    pub fn glfwSetCursorEnterCallback(window: *GLFWwindow, cbfun: Option<GLFWcursorenterfun>) -> Option<GLFWcursorenterfun>;
-    pub fn glfwSetScrollCallback(window: *GLFWwindow, cbfun: Option<GLFWscrollfun>) -> Option<GLFWscrollfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetKeyCallback(window: *GLFWwindow, cbfun: Option<GLFWkeyfun>) -> Option<GLFWkeyfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetCharCallback(window: *GLFWwindow, cbfun: Option<GLFWcharfun>) -> Option<GLFWcharfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetMouseButtonCallback(window: *GLFWwindow, cbfun: Option<GLFWmousebuttonfun>) -> Option<GLFWmousebuttonfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetCursorPosCallback(window: *GLFWwindow, cbfun: Option<GLFWcursorposfun>) -> Option<GLFWcursorposfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetCursorEnterCallback(window: *GLFWwindow, cbfun: Option<GLFWcursorenterfun>) -> Option<GLFWcursorenterfun>;
+    #[cfg(not(target_word_size = "32"))] pub fn glfwSetScrollCallback(window: *GLFWwindow, cbfun: Option<GLFWscrollfun>) -> Option<GLFWscrollfun>;
+    // FIXME: workaround for mozilla/rust#11040
+    #[cfg(target_word_size = "32")] pub fn glfwSetKeyCallback(window: *GLFWwindow, cbfun: GLFWkeyfun) -> GLFWkeyfun;
+    #[cfg(target_word_size = "32")] pub fn glfwSetCharCallback(window: *GLFWwindow, cbfun: GLFWcharfun) -> GLFWcharfun;
+    #[cfg(target_word_size = "32")] pub fn glfwSetMouseButtonCallback(window: *GLFWwindow, cbfun: GLFWmousebuttonfun) -> GLFWmousebuttonfun;
+    #[cfg(target_word_size = "32")] pub fn glfwSetCursorPosCallback(window: *GLFWwindow, cbfun: GLFWcursorposfun) -> GLFWcursorposfun;
+    #[cfg(target_word_size = "32")] pub fn glfwSetCursorEnterCallback(window: *GLFWwindow, cbfun: GLFWcursorenterfun) -> GLFWcursorenterfun;
+    #[cfg(target_word_size = "32")] pub fn glfwSetScrollCallback(window: *GLFWwindow, cbfun: GLFWscrollfun) -> GLFWscrollfun;
 
     pub fn glfwJoystickPresent(joy: c_int) -> c_int;
     pub fn glfwGetJoystickAxes(joy: c_int, count: *mut c_int) -> *c_float;
diff --git a/src/lib/lib.rs b/src/lib/lib.rs
index 0ee61f0e..b13430c4 100644
--- a/src/lib/lib.rs
+++ b/src/lib/lib.rs
@@ -1108,6 +1108,7 @@ pub struct Window {
     drop_receiver: Receiver<ContextDropped>
 }
 
+#[cfg(not(target_word_size = "32"))]
 macro_rules! set_window_callback(
     ($should_poll:expr, $ll_fn:ident, $callback:ident) => ({
         if $should_poll {
@@ -1117,6 +1118,17 @@ macro_rules! set_window_callback(
         }
     })
 )
+// FIXME: workaround for mozilla/rust#11040
+#[cfg(target_word_size = "32")]
+macro_rules! set_window_callback(
+    ($should_poll:expr, $ll_fn:ident, $callback:ident) => ({
+        if $should_poll {
+            unsafe { ffi::$ll_fn(self.ptr, callbacks::$callback); }
+        } else {
+            unsafe { ffi::$ll_fn(self.ptr, cast::transmute(ptr::null::<libc::c_void>())); }
+        }
+    })
+)
 
 impl Window {
     /// Wrapper for `glfwCreateWindow`.


Test patch: