* Crash in g_file_monitor on 32-bit Cygwin @ 2014-06-26 2:17 Ken Brown 2014-06-27 17:11 ` Ken Brown 0 siblings, 1 reply; 11+ messages in thread From: Ken Brown @ 2014-06-26 2:17 UTC (permalink / raw) To: cygwin This is a followup to https://cygwin.com/ml/cygwin/2014-06/msg00324.html, from which I extracted the following test case: $ cat gfile-test.c #include <stdio.h> #include <gio/gio.h> void gfile_add_watch (const char *file) { GFile *gfile = g_file_new_for_path (file); GFileMonitor *monitor; GFileMonitorFlags gflags = G_FILE_MONITOR_NONE; monitor = g_file_monitor (gfile, gflags, NULL, NULL); if (! monitor) printf ("Can't watch file %s\n", file); else printf ("Watching file %s\n", file); } int main () { const char *file = "gfile-test.c"; gfile_add_watch (file); } $ gcc -g -O0 -o gfile-test $(pkg-config --cflags gio-2.0) gfile-test.c $(pkg-config --libs gio-2.0) In the 64-bit case, this behaves as expected: $ ./gfile-test.exe Watching file gfile-test.c In the 32-bit case, however, it crashes. Running it under gdb shows that the call to g_file_monitor leads to a SEGV, but I can't tell exactly where; when I try to single step through the Glib code, I eventually hit an assertion violation in gdb. strace shows lots of exceptions, but I can't make much sense out of it otherwise. Ken -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Crash in g_file_monitor on 32-bit Cygwin 2014-06-26 2:17 Crash in g_file_monitor on 32-bit Cygwin Ken Brown @ 2014-06-27 17:11 ` Ken Brown 2014-06-27 17:16 ` Ken Brown 2014-06-27 17:52 ` Yaakov Selkowitz 0 siblings, 2 replies; 11+ messages in thread From: Ken Brown @ 2014-06-27 17:11 UTC (permalink / raw) To: cygwin On 6/25/2014 10:17 PM, Ken Brown wrote: > This is a followup to https://cygwin.com/ml/cygwin/2014-06/msg00324.html, from which I extracted the following test case: > > $ cat gfile-test.c > #include <stdio.h> > #include <gio/gio.h> > > void > gfile_add_watch (const char *file) > { > GFile *gfile = g_file_new_for_path (file); > GFileMonitor *monitor; > GFileMonitorFlags gflags = G_FILE_MONITOR_NONE; > monitor = g_file_monitor (gfile, gflags, NULL, NULL); > if (! monitor) > printf ("Can't watch file %s\n", file); > else > printf ("Watching file %s\n", file); > } > > int > main () > { > const char *file = "gfile-test.c"; > gfile_add_watch (file); > } > > $ gcc -g -O0 -o gfile-test $(pkg-config --cflags gio-2.0) gfile-test.c $(pkg-config --libs gio-2.0) > > In the 64-bit case, this behaves as expected: > > $ ./gfile-test.exe > Watching file gfile-test.c > > In the 32-bit case, however, it crashes. Running it under gdb shows > that the call to g_file_monitor leads to a SEGV, but I can't tell > exactly where; when I try to single step through the Glib code, I > eventually hit an assertion violation in gdb. strace shows lots of > exceptions, but I can't make much sense out of it otherwise. I rebuilt glib and gamin without optimization so that I could step through the code in gdb. But stepping through the code turned out to be unnecessary, because the bug was gone after the rebuilds. I don't know if optimization was really the issue or whether just rebuilding with the latest tools is what fixed it. My builds can be obtained from http://sanibeltranquility.com/cygwin/ if anyone else wants to try to reproduce this without rebuilding the packages themselves. Yaakov, could you take a look? Ken -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Crash in g_file_monitor on 32-bit Cygwin 2014-06-27 17:11 ` Ken Brown @ 2014-06-27 17:16 ` Ken Brown 2014-06-27 17:52 ` Yaakov Selkowitz 1 sibling, 0 replies; 11+ messages in thread From: Ken Brown @ 2014-06-27 17:16 UTC (permalink / raw) To: cygwin On 6/27/2014 1:11 PM, Ken Brown wrote: > My builds can be obtained from > > http://sanibeltranquility.com/cygwin/ > > if anyone else wants to try to reproduce this without rebuilding the > packages themselves. I forgot to say that you'll probably have to run rebaseall after the install. Ken -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Crash in g_file_monitor on 32-bit Cygwin 2014-06-27 17:11 ` Ken Brown 2014-06-27 17:16 ` Ken Brown @ 2014-06-27 17:52 ` Yaakov Selkowitz 2014-06-28 11:08 ` Ken Brown 1 sibling, 1 reply; 11+ messages in thread From: Yaakov Selkowitz @ 2014-06-27 17:52 UTC (permalink / raw) To: cygwin On 2014-06-27 12:11, Ken Brown wrote: > On 6/25/2014 10:17 PM, Ken Brown wrote: >> This is a followup to >> https://cygwin.com/ml/cygwin/2014-06/msg00324.html, from which I >> extracted the following test case: >> >> $ cat gfile-test.c >> #include <stdio.h> >> #include <gio/gio.h> >> >> void >> gfile_add_watch (const char *file) >> { >> GFile *gfile = g_file_new_for_path (file); >> GFileMonitor *monitor; >> GFileMonitorFlags gflags = G_FILE_MONITOR_NONE; >> monitor = g_file_monitor (gfile, gflags, NULL, NULL); >> if (! monitor) >> printf ("Can't watch file %s\n", file); >> else >> printf ("Watching file %s\n", file); >> } >> >> int >> main () >> { >> const char *file = "gfile-test.c"; >> gfile_add_watch (file); >> } >> >> $ gcc -g -O0 -o gfile-test $(pkg-config --cflags gio-2.0) gfile-test.c >> $(pkg-config --libs gio-2.0) >> >> In the 64-bit case, this behaves as expected: >> >> $ ./gfile-test.exe >> Watching file gfile-test.c >> >> In the 32-bit case, however, it crashes. Running it under gdb shows >> that the call to g_file_monitor leads to a SEGV, but I can't tell >> exactly where; when I try to single step through the Glib code, I >> eventually hit an assertion violation in gdb. strace shows lots of >> exceptions, but I can't make much sense out of it otherwise. > > I rebuilt glib and gamin without optimization so that I could step > through the code in gdb. But stepping through the code turned out to be > unnecessary, because the bug was gone after the rebuilds. I don't know > if optimization was really the issue or whether just rebuilding with the > latest tools is what fixed it. > > My builds can be obtained from > > http://sanibeltranquility.com/cygwin/ > > if anyone else wants to try to reproduce this without rebuilding the > packages themselves. > > Yaakov, could you take a look? Sure. Are you narrow this down to only one of glib or gamin? Yaakov -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Crash in g_file_monitor on 32-bit Cygwin 2014-06-27 17:52 ` Yaakov Selkowitz @ 2014-06-28 11:08 ` Ken Brown 2014-10-14 16:27 ` Ken Brown 0 siblings, 1 reply; 11+ messages in thread From: Ken Brown @ 2014-06-28 11:08 UTC (permalink / raw) To: cygwin On 6/27/2014 1:52 PM, Yaakov Selkowitz wrote: > On 2014-06-27 12:11, Ken Brown wrote: >> On 6/25/2014 10:17 PM, Ken Brown wrote: >>> This is a followup to >>> https://cygwin.com/ml/cygwin/2014-06/msg00324.html, from which I >>> extracted the following test case: >>> >>> $ cat gfile-test.c >>> #include <stdio.h> >>> #include <gio/gio.h> >>> >>> void >>> gfile_add_watch (const char *file) >>> { >>> GFile *gfile = g_file_new_for_path (file); >>> GFileMonitor *monitor; >>> GFileMonitorFlags gflags = G_FILE_MONITOR_NONE; >>> monitor = g_file_monitor (gfile, gflags, NULL, NULL); >>> if (! monitor) >>> printf ("Can't watch file %s\n", file); >>> else >>> printf ("Watching file %s\n", file); >>> } >>> >>> int >>> main () >>> { >>> const char *file = "gfile-test.c"; >>> gfile_add_watch (file); >>> } >>> >>> $ gcc -g -O0 -o gfile-test $(pkg-config --cflags gio-2.0) gfile-test.c >>> $(pkg-config --libs gio-2.0) >>> >>> In the 64-bit case, this behaves as expected: >>> >>> $ ./gfile-test.exe >>> Watching file gfile-test.c >>> >>> In the 32-bit case, however, it crashes. Running it under gdb shows >>> that the call to g_file_monitor leads to a SEGV, but I can't tell >>> exactly where; when I try to single step through the Glib code, I >>> eventually hit an assertion violation in gdb. strace shows lots of >>> exceptions, but I can't make much sense out of it otherwise. >> >> I rebuilt glib and gamin without optimization so that I could step >> through the code in gdb. But stepping through the code turned out to be >> unnecessary, because the bug was gone after the rebuilds. I don't know >> if optimization was really the issue or whether just rebuilding with the >> latest tools is what fixed it. >> >> My builds can be obtained from >> >> http://sanibeltranquility.com/cygwin/ >> >> if anyone else wants to try to reproduce this without rebuilding the >> packages themselves. >> >> Yaakov, could you take a look? > > Sure. Are you narrow this down to only one of glib or gamin? The culprit is gamin, and optimization *is* relevant. What's strange, though, is that when I rebuild it with optimization, my test case hangs instead of crashing. Summary: - With gamin-0.1.10-14 (and its subpackages), my test case crashes. The outward symptom is that there's no output, but running the test case under gdb shows the SEGV. - If I rebuild gamin without optimization, I don't see any bug. More precisely, I build it using your gamin.cygport with the following line added: CFLAGS+=" -O0 -g3" - If I rebuild gamin with optimization (i.e., just using your gamin.cygport with no changes), my test case hangs. Ken -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Crash in g_file_monitor on 32-bit Cygwin 2014-06-28 11:08 ` Ken Brown @ 2014-10-14 16:27 ` Ken Brown 2014-10-14 18:30 ` Ken Brown 0 siblings, 1 reply; 11+ messages in thread From: Ken Brown @ 2014-10-14 16:27 UTC (permalink / raw) To: cygwin On 6/28/2014 7:08 AM, Ken Brown wrote: > On 6/27/2014 1:52 PM, Yaakov Selkowitz wrote: >> On 2014-06-27 12:11, Ken Brown wrote: >>> On 6/25/2014 10:17 PM, Ken Brown wrote: >>>> This is a followup to >>>> https://cygwin.com/ml/cygwin/2014-06/msg00324.html, from which I >>>> extracted the following test case: >>>> >>>> $ cat gfile-test.c >>>> #include <stdio.h> >>>> #include <gio/gio.h> >>>> >>>> void >>>> gfile_add_watch (const char *file) >>>> { >>>> GFile *gfile = g_file_new_for_path (file); >>>> GFileMonitor *monitor; >>>> GFileMonitorFlags gflags = G_FILE_MONITOR_NONE; >>>> monitor = g_file_monitor (gfile, gflags, NULL, NULL); >>>> if (! monitor) >>>> printf ("Can't watch file %s\n", file); >>>> else >>>> printf ("Watching file %s\n", file); >>>> } >>>> >>>> int >>>> main () >>>> { >>>> const char *file = "gfile-test.c"; >>>> gfile_add_watch (file); >>>> } >>>> >>>> $ gcc -g -O0 -o gfile-test $(pkg-config --cflags gio-2.0) gfile-test.c >>>> $(pkg-config --libs gio-2.0) >>>> >>>> In the 64-bit case, this behaves as expected: >>>> >>>> $ ./gfile-test.exe >>>> Watching file gfile-test.c >>>> >>>> In the 32-bit case, however, it crashes. Running it under gdb shows >>>> that the call to g_file_monitor leads to a SEGV, but I can't tell >>>> exactly where; when I try to single step through the Glib code, I >>>> eventually hit an assertion violation in gdb. strace shows lots of >>>> exceptions, but I can't make much sense out of it otherwise. >>> >>> I rebuilt glib and gamin without optimization so that I could step >>> through the code in gdb. But stepping through the code turned out to be >>> unnecessary, because the bug was gone after the rebuilds. I don't know >>> if optimization was really the issue or whether just rebuilding with the >>> latest tools is what fixed it. >>> >>> My builds can be obtained from >>> >>> http://sanibeltranquility.com/cygwin/ >>> >>> if anyone else wants to try to reproduce this without rebuilding the >>> packages themselves. >>> >>> Yaakov, could you take a look? >> >> Sure. Are you narrow this down to only one of glib or gamin? > > The culprit is gamin, and optimization *is* relevant. What's strange, though, > is that when I rebuild it with optimization, my test case hangs instead of > crashing. Summary: > > - With gamin-0.1.10-14 (and its subpackages), my test case crashes. The outward > symptom is that there's no output, but running the test case under gdb shows the > SEGV. > > - If I rebuild gamin without optimization, I don't see any bug. More precisely, > I build it using your gamin.cygport with the following line added: > > CFLAGS+=" -O0 -g3" > > - If I rebuild gamin with optimization (i.e., just using your gamin.cygport with > no changes), my test case hangs. I made another attempt to debug this, and I found the problem, but I don't know how to fix it. First, I have to correct the last assertion I made above about my test case hanging; I just didn't wait long enough for it to finish. What happens is that there is a retry loop in libgamin/gam_api.c:gamin_connect_unix_socket that gives up after 25 seconds. And the reason it fails is that /usr/libexec/gam_server.exe has crashed. In fact, the latter always crashes on 32-bit Cygwin if it's built with optimization and if the directory /tmp/fam-<username> exists before it is run. [And this directory will always exist after one run of gam_server.exe.] The crash occurs in a call to g_free at server/gam_channel.c:525 because the pointer 'dir' that is being freed has been clobbered by a call to gam_check_not_fat on line 497. Here are some details, based on a build using Yaakov's gamin.cygport file with the added line CFLAGS+=" -O1 -g3" I've appended at the end of this message a transcript of a gdb session that illustrates some of the assertions I'll be making. At line 447 of server/gam_channel.c, g_strconcat is called to get a pointer to the directory name "/tmp/fam-<username>". The value of this pointer is assigned to the variable 'dir' at line 473, and in my run it is 0x8005c068. Although 'dir' is optimized out, I can see from a disassembly that the pointer is stored on the stack at -0x510(%ebp): 0x004058fc <+266>: call 0x408bf8 <g_strconcat> 0x00405901 <+271>: mov %eax,-0x510(%ebp) And I verified in my gdb session that this stack location does indeed contain 0x8005c068. After the call to gam_check_not_fat a little later, that stack location contains the value 0x00000104. Then when g_free attempts to free the bogus pointer 0x00000104, we get a crash. I can't tell from the disassembly why the call to gam_check_not_fat clobbers the stack. My best guess is that it happens as a result of calls to some Windows functions. I hope someone more knowledgeable can take this further and fix it. By the way, the problem doesn't occur in the 64-bit case because the pointer 'dir' is saved in a register rather than on the stack, and apparently (by luck?) this register is not clobbered by gam_check_not_fat. Ken P.S. I think I found a typo in gam_check_not_fat, unrelated to the present problem. Based on the context and the indentation, I think a couple of lines need to be enclosed in braces: --- gam_channel.c.orig 2014-10-14 12:08:55.000000000 -0400 +++ gam_channel.c 2014-10-14 09:46:37.746490800 -0400 @@ -44,8 +44,10 @@ && (c = strchr (root + 3, '\\'))) c[1] = '\0'; else - fprintf (stderr, "GetVolumePathName: %d\n", GetLastError ()); - return 0; + { + fprintf (stderr, "GetVolumePathName: %d\n", GetLastError ()); + return 0; + } } if (!GetVolumeInformation (root, volname, MAX_PATH, NULL, NULL, NULL, fsname, MAX_PATH)) =======================GDB transcript========================= $ gdb /usr/libexec/gam_server.exe GNU gdb (GDB) 7.8 [...] Reading symbols from /usr/libexec/gam_server.exe...Reading symbols from /usr/lib/debug//usr/libexec/gam_server.exe.dbg...done. (gdb) b gam_check_secure_dir Breakpoint 1 at 0x4058b1: file /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c, line 441. (gdb) r Starting program: /usr/libexec/gam_server.exe [New Thread 11320.0x61c] [New Thread 11320.0x3abc] Breakpoint 1, gam_listen_unix_socket (path=<optimized out>) at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:699 699 if (!gam_check_secure_dir()) { (gdb) s gam_check_secure_dir () at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:699 699 if (!gam_check_secure_dir()) { (gdb) gam_get_socket_dir () at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:441 441 user = g_get_user_name(); (gdb) n 443 if (user == NULL) { (gdb) 447 ret = g_strconcat("/tmp/fam-", user, NULL); (gdb) s g_strconcat ( string1=string1@entry=0x40c2cf <__FUNCTION__.10927+222> "/tmp/fam-") at /usr/src/debug/glib2.0-2.38.2-4/glib/gstrfuncs.c:569 569 { (gdb) fin Run till exit from #0 g_strconcat ( string1=string1@entry=0x40c2cf <__FUNCTION__.10927+222> "/tmp/fam-") at /usr/src/debug/glib2.0-2.38.2-4/glib/gstrfuncs.c:569 0x00405901 in gam_get_socket_dir () at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:447 447 ret = g_strconcat("/tmp/fam-", user, NULL); Value returned is $1 = (gchar *) 0x8005c068 "/tmp/fam-kbrown" (gdb) n gam_check_secure_dir () at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:476 476 if (dir == NULL) { (gdb) s 481 ret = mkdir(dir, 0700); (gdb) p dir $2 = <optimized out> (gdb) x/x $ebp-0x510 0x28a6a8: 0x8005c068 <<<<<<<<<<<<<<<<<<<<<<<<<< (gdb) n 482 if (ret >= 0) { (gdb) 488 switch (errno) { (gdb) 490 ret = stat(dir, &st); (gdb) 491 if (ret < 0) { (gdb) 497 not_fat = gam_check_not_fat(dir); (gdb) 498 if (not_fat && (st.st_uid != getuid())) { (gdb) x/x $ebp-0x510 0x28a6a8: 0x00000104 <<<<<<<<<<<<<<<<<<<<<<<<<<< (gdb) n gam_server_create (session=0x0) at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:816 816 fd = gam_listen_unix_socket(path); (gdb) s gam_listen_unix_socket (path=<optimized out>) at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:816 816 fd = gam_listen_unix_socket(path); (gdb) gam_check_secure_dir () at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:504 504 if (!S_ISDIR (st.st_mode)) { (gdb) 509 if (not_fat && (st.st_mode & (S_IRWXG|S_IRWXO))) { (gdb) 515 if (not_fat && ((st.st_mode & (S_IRWXU)) != S_IRWXU)) { (gdb) 524 GAM_DEBUG(DEBUG_INFO, "Reusing socket directory %s\n", dir); (gdb) 525 g_free(dir); (gdb) g_free (mem=0x104) at /usr/src/debug/glib2.0-2.38.2-4/glib/gmem.c:195 195 { (gdb) fin Run till exit from #0 g_free (mem=0x104) at /usr/src/debug/glib2.0-2.38.2-4/glib/gmem.c:195 Program received signal SIGABRT, Aborted. 0x00405d0b in gam_check_secure_dir () at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:525 525 g_free(dir); (gdb) bt #0 0x00405d0b in gam_check_secure_dir () at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:525 #1 gam_listen_unix_socket (path=<optimized out>) at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:699 #2 gam_server_create ( session=0x1ac <error: Cannot access memory at address 0x1ac>) at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:816 #3 0x76891194 in WaitForSingleObjectEx () from /c/Windows/syswow64/kernel32.dll #4 0x76891148 in WaitForSingleObject () from /c/Windows/syswow64/kernel32.dll #5 0x610db4f6 in sig_send(_pinfo*, siginfo_t&, _cygtls*)@12 ( p=p@entry=0x60fd0000, si=..., tls=tls@entry=0x0) at /usr/src/debug/cygwin-1.7.32-1/winsup/cygwin/sigproc.cc:679 #6 0x610d8a2c in _pinfo::kill(siginfo_t&)@8 (this=0x60fd0000, si=...) at /usr/src/debug/cygwin-1.7.32-1/winsup/cygwin/signal.cc:248 #7 0x610d8ef6 in kill0 (pid=pid@entry=11372, si=...) at /usr/src/debug/cygwin-1.7.32-1/winsup/cygwin/signal.cc:299 #8 0x610d90c2 in kill (sig=sig@entry=6, pid=11372) at /usr/src/debug/cygwin-1.7.32-1/winsup/cygwin/signal.cc:308 #9 raise (sig=sig@entry=6) at /usr/src/debug/cygwin-1.7.32-1/winsup/cygwin/signal.cc:284 #10 0x610d9363 in abort () at /usr/src/debug/cygwin-1.7.32-1/winsup/cygwin/signal.cc:371 #11 0x61108166 in dlfree@4 (mem=0x0, mem@entry=0x104) at /usr/src/debug/cygwin-1.7.32-1/winsup/cygwin/malloc.cc:4248 #12 0x61082560 in free (p=0x104) at /usr/src/debug/cygwin-1.7.32-1/winsup/cygwin/malloc_wrapper.cc:47 #13 0x610d57f5 in _sigfe () from /usr/bin/cygwin1.dll #14 0x00000000 in ?? () -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Crash in g_file_monitor on 32-bit Cygwin 2014-10-14 16:27 ` Ken Brown @ 2014-10-14 18:30 ` Ken Brown 2014-10-14 19:28 ` Corinna Vinschen 2014-10-15 16:46 ` Yaakov Selkowitz 0 siblings, 2 replies; 11+ messages in thread From: Ken Brown @ 2014-10-14 18:30 UTC (permalink / raw) To: cygwin On 10/14/2014 12:26 PM, Ken Brown wrote: > On 6/28/2014 7:08 AM, Ken Brown wrote: >> On 6/27/2014 1:52 PM, Yaakov Selkowitz wrote: >>> On 2014-06-27 12:11, Ken Brown wrote: >>>> On 6/25/2014 10:17 PM, Ken Brown wrote: >>>>> This is a followup to >>>>> https://cygwin.com/ml/cygwin/2014-06/msg00324.html, from which I >>>>> extracted the following test case: >>>>> >>>>> $ cat gfile-test.c >>>>> #include <stdio.h> >>>>> #include <gio/gio.h> >>>>> >>>>> void >>>>> gfile_add_watch (const char *file) >>>>> { >>>>> GFile *gfile = g_file_new_for_path (file); >>>>> GFileMonitor *monitor; >>>>> GFileMonitorFlags gflags = G_FILE_MONITOR_NONE; >>>>> monitor = g_file_monitor (gfile, gflags, NULL, NULL); >>>>> if (! monitor) >>>>> printf ("Can't watch file %s\n", file); >>>>> else >>>>> printf ("Watching file %s\n", file); >>>>> } >>>>> >>>>> int >>>>> main () >>>>> { >>>>> const char *file = "gfile-test.c"; >>>>> gfile_add_watch (file); >>>>> } >>>>> >>>>> $ gcc -g -O0 -o gfile-test $(pkg-config --cflags gio-2.0) gfile-test.c >>>>> $(pkg-config --libs gio-2.0) >>>>> >>>>> In the 64-bit case, this behaves as expected: >>>>> >>>>> $ ./gfile-test.exe >>>>> Watching file gfile-test.c >>>>> >>>>> In the 32-bit case, however, it crashes. Running it under gdb shows >>>>> that the call to g_file_monitor leads to a SEGV, but I can't tell >>>>> exactly where; when I try to single step through the Glib code, I >>>>> eventually hit an assertion violation in gdb. strace shows lots of >>>>> exceptions, but I can't make much sense out of it otherwise. >>>> >>>> I rebuilt glib and gamin without optimization so that I could step >>>> through the code in gdb. But stepping through the code turned out to be >>>> unnecessary, because the bug was gone after the rebuilds. I don't know >>>> if optimization was really the issue or whether just rebuilding with the >>>> latest tools is what fixed it. >>>> >>>> My builds can be obtained from >>>> >>>> http://sanibeltranquility.com/cygwin/ >>>> >>>> if anyone else wants to try to reproduce this without rebuilding the >>>> packages themselves. >>>> >>>> Yaakov, could you take a look? >>> >>> Sure. Are you narrow this down to only one of glib or gamin? >> >> The culprit is gamin, and optimization *is* relevant. What's strange, though, >> is that when I rebuild it with optimization, my test case hangs instead of >> crashing. Summary: >> >> - With gamin-0.1.10-14 (and its subpackages), my test case crashes. The outward >> symptom is that there's no output, but running the test case under gdb shows the >> SEGV. >> >> - If I rebuild gamin without optimization, I don't see any bug. More precisely, >> I build it using your gamin.cygport with the following line added: >> >> CFLAGS+=" -O0 -g3" >> >> - If I rebuild gamin with optimization (i.e., just using your gamin.cygport with >> no changes), my test case hangs. > > I made another attempt to debug this, and I found the problem, but I don't know > how to fix it. First, I have to correct the last assertion I made above about > my test case hanging; I just didn't wait long enough for it to finish. What > happens is that there is a retry loop in > libgamin/gam_api.c:gamin_connect_unix_socket that gives up after 25 seconds. And > the reason it fails is that /usr/libexec/gam_server.exe has crashed. In fact, > the latter always crashes on 32-bit Cygwin if it's built with optimization and > if the directory /tmp/fam-<username> exists before it is run. [And this > directory will always exist after one run of gam_server.exe.] > > The crash occurs in a call to g_free at server/gam_channel.c:525 because the > pointer 'dir' that is being freed has been clobbered by a call to > gam_check_not_fat on line 497. Here are some details, based on a build using > Yaakov's gamin.cygport file with the added line > > CFLAGS+=" -O1 -g3" > > I've appended at the end of this message a transcript of a gdb session that > illustrates some of the assertions I'll be making. > > At line 447 of server/gam_channel.c, g_strconcat is called to get a pointer to > the directory name "/tmp/fam-<username>". The value of this pointer is assigned > to the variable 'dir' at line 473, and in my run it is 0x8005c068. Although > 'dir' is optimized out, I can see from a disassembly that the pointer is stored > on the stack at -0x510(%ebp): > > 0x004058fc <+266>: call 0x408bf8 <g_strconcat> > 0x00405901 <+271>: mov %eax,-0x510(%ebp) > > And I verified in my gdb session that this stack location does indeed contain > 0x8005c068. After the call to gam_check_not_fat a little later, that stack > location contains the value 0x00000104. Then when g_free attempts to free the > bogus pointer 0x00000104, we get a crash. > > I can't tell from the disassembly why the call to gam_check_not_fat clobbers the > stack. My best guess is that it happens as a result of calls to some Windows > functions. I hope someone more knowledgeable can take this further and fix it. I stepped into gam_check_not_fat (which I should have done to begin with) and narrowed this down further. The stack location in question gets clobbered by the call to GetVolumeInformation: (gdb) s gam_check_not_fat (path=0x8005c068 "/tmp/fam-kbrown") at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:35 35 cygwin_conv_path(CCP_POSIX_TO_WIN_A, path, winpath, MAX_PATH); (gdb) x/x $ebp-0x510 0x28a6a8: 0x8005c068 (gdb) n 37 pGVPN = GetProcAddress(LoadLibrary("kernel32"), "GetVolumePathNameA"); (gdb) x/x $ebp-0x510 0x28a6a8: 0x8005c068 (gdb) n 38 if (!pGVPN || !(pGVPN)(winpath, root, MAX_PATH)) (gdb) x/x $ebp-0x510 0x28a6a8: 0x8005c068 (gdb) n 52 if (!GetVolumeInformation (root, volname, MAX_PATH, NULL, (gdb) x/x $ebp-0x510 0x28a6a8: 0x8005c068 (gdb) n 58 if (!strncmp(fsname, "FAT", 3)) /* FAT, FAT32 */ (gdb) x/x $ebp-0x510 0x28a6a8: 0x00000104 Here's the code near the call to GetVolumeInformation, followed by what I think is the relevant disassembly: if (!GetVolumeInformation (root, volname, MAX_PATH, NULL, NULL, NULL, fsname, MAX_PATH)) { fprintf (stderr, "GetVolumeInformation: %d\n", GetLastError ()); return 0; } 0x00405b3a <+840>: movl $0x104,0x1c(%esp) <<<<<<<<<<<<<<<< 0x00405b42 <+848>: lea -0x120(%ebp),%eax 0x00405b48 <+854>: mov %eax,0x18(%esp) 0x00405b4c <+858>: movl $0x0,0x14(%esp) 0x00405b54 <+866>: movl $0x0,0x10(%esp) 0x00405b5c <+874>: movl $0x0,0xc(%esp) 0x00405b64 <+882>: movl $0x104,0x8(%esp) <<<<<<<<<<<<<<<< 0x00405b6c <+890>: lea -0x224(%ebp),%eax 0x00405b72 <+896>: mov %eax,0x4(%esp) 0x00405b76 <+900>: lea -0x328(%ebp),%eax 0x00405b7c <+906>: mov %eax,(%esp) 0x00405b7f <+909>: call *0x41248c <----- GetVolumeInformation? 0x00405b85 <+915>: sub $0x20,%esp 0x00405b88 <+918>: test %eax,%eax 0x00405b8a <+920>: jne 0x405bb5 <gam_server_create+963> 0x00405b8c <+922>: call *0x412480 <----- GetLastError? 0x00405b92 <+928>: mov %eax,%esi 0x00405b94 <+930>: call 0x408df0 <__getreent> 0x00405b99 <+935>: mov %esi,0x8(%esp) 0x00405b9d <+939>: movl $0x40c70f,0x4(%esp) 0x00405ba5 <+947>: mov 0xc(%eax),%eax 0x00405ba8 <+950>: mov %eax,(%esp) 0x00405bab <+953>: call 0x408df8 <fprintf> 0x00405bb0 <+958>: jmp 0x406073 <gam_server_create+2177> Note the two marked movl instructions involving 0x104; I guess one of these is the culprit, but I don't really know what's going on. Ken -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Crash in g_file_monitor on 32-bit Cygwin 2014-10-14 18:30 ` Ken Brown @ 2014-10-14 19:28 ` Corinna Vinschen 2014-10-14 21:09 ` Yaakov Selkowitz 2014-10-15 16:46 ` Yaakov Selkowitz 1 sibling, 1 reply; 11+ messages in thread From: Corinna Vinschen @ 2014-10-14 19:28 UTC (permalink / raw) To: cygwin [-- Attachment #1: Type: text/plain, Size: 2042 bytes --] Hi Ken, I know the code is not yours, but I have to vent while I see this code :) On Oct 14 14:30, Ken Brown wrote: > I stepped into gam_check_not_fat (which I should have done to begin with) > and narrowed this down further. The stack location in question gets > clobbered by the call to GetVolumeInformation: > > (gdb) s > gam_check_not_fat (path=0x8005c068 "/tmp/fam-kbrown") > at /usr/src/debug/gamin-0.1.10-16/server/gam_channel.c:35 > 35 cygwin_conv_path(CCP_POSIX_TO_WIN_A, path, winpath, MAX_PATH); Ouch. What about paths longer than MAX_PATH? > (gdb) x/x $ebp-0x510 > 0x28a6a8: 0x8005c068 > (gdb) n > 37 pGVPN = GetProcAddress(LoadLibrary("kernel32"), "GetVolumePathNameA"); There's no reason to load GetVolumePathName from kernel32 since all supported platforms provide this entry point. > (gdb) x/x $ebp-0x510 > 0x28a6a8: 0x8005c068 > (gdb) n > 38 if (!pGVPN || !(pGVPN)(winpath, root, MAX_PATH)) > (gdb) x/x $ebp-0x510 > 0x28a6a8: 0x8005c068 > (gdb) n > 52 if (!GetVolumeInformation (root, volname, MAX_PATH, NULL, > (gdb) x/x $ebp-0x510 > 0x28a6a8: 0x8005c068 > (gdb) n > 58 if (!strncmp(fsname, "FAT", 3)) /* FAT, FAT32 */ How old is this code? What *exactly* is this function trying to check? I assume it's checking for certain filesystem capabilities, but then, there's no good reason to check for a filesystem being "FAT" or "FAT32". Any other filesystem might have the same or similar capabilities and be called "FOOBAR". Whatever the code is doing, it should probably simply call statvfs() and check the f_flag member of the returned struct statvfs for a certain flag. The flags returned in f_flag are the same as the fs flags returned by GetVolumeInformation. So, what is it the code is trying to test by checking the FS name? Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat [-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Crash in g_file_monitor on 32-bit Cygwin 2014-10-14 19:28 ` Corinna Vinschen @ 2014-10-14 21:09 ` Yaakov Selkowitz 0 siblings, 0 replies; 11+ messages in thread From: Yaakov Selkowitz @ 2014-10-14 21:09 UTC (permalink / raw) To: cygwin On 2014-10-14 14:28, Corinna Vinschen wrote: > I know the code is not yours, but I have to vent while I see this code :) Actually, this isn't the first time you're seeing this code, it's just been a while. :-) > There's no reason to load GetVolumePathName from kernel32 since all supported > platforms provide this entry point. They didn't when this code was written. > How old is this code? 2006. > What *exactly* is this function trying to check? gamin enforces permissions on its sockets, which will fail on FAT partitions for obvious reasons, so we need to bypass those checks in that case. Obviously this code is overdue for an update, which I'll try to do later today. Yaakov -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Crash in g_file_monitor on 32-bit Cygwin 2014-10-14 18:30 ` Ken Brown 2014-10-14 19:28 ` Corinna Vinschen @ 2014-10-15 16:46 ` Yaakov Selkowitz 2014-10-16 1:11 ` Ken Brown 1 sibling, 1 reply; 11+ messages in thread From: Yaakov Selkowitz @ 2014-10-15 16:46 UTC (permalink / raw) To: cygwin On 2014-10-14 13:30, Ken Brown wrote: > I stepped into gam_check_not_fat (which I should have done to begin > with) and narrowed this down further. The stack location in question > gets clobbered by the call to GetVolumeInformation: [snip] > Here's the code near the call to GetVolumeInformation, followed by what > I think is the relevant disassembly: > > if (!GetVolumeInformation (root, volname, MAX_PATH, NULL, > NULL, NULL, fsname, MAX_PATH)) > { > fprintf (stderr, "GetVolumeInformation: %d\n", GetLastError ()); > return 0; > } > > 0x00405b3a <+840>: movl $0x104,0x1c(%esp) <<<<<<<<<<<<<<<< > 0x00405b42 <+848>: lea -0x120(%ebp),%eax > 0x00405b48 <+854>: mov %eax,0x18(%esp) > 0x00405b4c <+858>: movl $0x0,0x14(%esp) > 0x00405b54 <+866>: movl $0x0,0x10(%esp) > 0x00405b5c <+874>: movl $0x0,0xc(%esp) > 0x00405b64 <+882>: movl $0x104,0x8(%esp) <<<<<<<<<<<<<<<< > 0x00405b6c <+890>: lea -0x224(%ebp),%eax > 0x00405b72 <+896>: mov %eax,0x4(%esp) > 0x00405b76 <+900>: lea -0x328(%ebp),%eax > 0x00405b7c <+906>: mov %eax,(%esp) > 0x00405b7f <+909>: call *0x41248c <----- GetVolumeInformation? > 0x00405b85 <+915>: sub $0x20,%esp > 0x00405b88 <+918>: test %eax,%eax > 0x00405b8a <+920>: jne 0x405bb5 <gam_server_create+963> > 0x00405b8c <+922>: call *0x412480 <----- GetLastError? > 0x00405b92 <+928>: mov %eax,%esi > 0x00405b94 <+930>: call 0x408df0 <__getreent> > 0x00405b99 <+935>: mov %esi,0x8(%esp) > 0x00405b9d <+939>: movl $0x40c70f,0x4(%esp) > 0x00405ba5 <+947>: mov 0xc(%eax),%eax > 0x00405ba8 <+950>: mov %eax,(%esp) > 0x00405bab <+953>: call 0x408df8 <fprintf> > 0x00405bb0 <+958>: jmp 0x406073 <gam_server_create+2177> > > Note the two marked movl instructions involving 0x104; I guess one of > these is the culprit, but I don't really know what's going on. While it should be purely academic now, the issue might have been a failure to mark pGVPN as WINAPI (IOW __stdcall on x86): - BOOL (*pGVPN)(LPCTSTR, LPTSTR, DWORD); + BOOL (WINAPI *pGVPN)(LPCTSTR, LPTSTR, DWORD); Something must have changed in gcc's optimization that this triggered; it certainly wasn't an issue when the code was first introduced. Thanks for tracking this down; gamin-0.1.10-15 uses more modern features to test for FAT that weren't available back in 2006. Yaakov -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Crash in g_file_monitor on 32-bit Cygwin 2014-10-15 16:46 ` Yaakov Selkowitz @ 2014-10-16 1:11 ` Ken Brown 0 siblings, 0 replies; 11+ messages in thread From: Ken Brown @ 2014-10-16 1:11 UTC (permalink / raw) To: cygwin On 10/15/2014 12:46 PM, Yaakov Selkowitz wrote: > On 2014-10-14 13:30, Ken Brown wrote: >> I stepped into gam_check_not_fat (which I should have done to begin >> with) and narrowed this down further. The stack location in question >> gets clobbered by the call to GetVolumeInformation: > [snip] >> Here's the code near the call to GetVolumeInformation, followed by what >> I think is the relevant disassembly: >> >> if (!GetVolumeInformation (root, volname, MAX_PATH, NULL, >> NULL, NULL, fsname, MAX_PATH)) >> { >> fprintf (stderr, "GetVolumeInformation: %d\n", GetLastError ()); >> return 0; >> } >> >> 0x00405b3a <+840>: movl $0x104,0x1c(%esp) <<<<<<<<<<<<<<<< >> 0x00405b42 <+848>: lea -0x120(%ebp),%eax >> 0x00405b48 <+854>: mov %eax,0x18(%esp) >> 0x00405b4c <+858>: movl $0x0,0x14(%esp) >> 0x00405b54 <+866>: movl $0x0,0x10(%esp) >> 0x00405b5c <+874>: movl $0x0,0xc(%esp) >> 0x00405b64 <+882>: movl $0x104,0x8(%esp) <<<<<<<<<<<<<<<< >> 0x00405b6c <+890>: lea -0x224(%ebp),%eax >> 0x00405b72 <+896>: mov %eax,0x4(%esp) >> 0x00405b76 <+900>: lea -0x328(%ebp),%eax >> 0x00405b7c <+906>: mov %eax,(%esp) >> 0x00405b7f <+909>: call *0x41248c <----- GetVolumeInformation? >> 0x00405b85 <+915>: sub $0x20,%esp >> 0x00405b88 <+918>: test %eax,%eax >> 0x00405b8a <+920>: jne 0x405bb5 <gam_server_create+963> >> 0x00405b8c <+922>: call *0x412480 <----- GetLastError? >> 0x00405b92 <+928>: mov %eax,%esi >> 0x00405b94 <+930>: call 0x408df0 <__getreent> >> 0x00405b99 <+935>: mov %esi,0x8(%esp) >> 0x00405b9d <+939>: movl $0x40c70f,0x4(%esp) >> 0x00405ba5 <+947>: mov 0xc(%eax),%eax >> 0x00405ba8 <+950>: mov %eax,(%esp) >> 0x00405bab <+953>: call 0x408df8 <fprintf> >> 0x00405bb0 <+958>: jmp 0x406073 <gam_server_create+2177> >> >> Note the two marked movl instructions involving 0x104; I guess one of >> these is the culprit, but I don't really know what's going on. > > While it should be purely academic now, the issue might have been a failure to > mark pGVPN as WINAPI (IOW __stdcall on x86): > > - BOOL (*pGVPN)(LPCTSTR, LPTSTR, DWORD); > + BOOL (WINAPI *pGVPN)(LPCTSTR, LPTSTR, DWORD); Ah, that makes sense. Thanks. I'm glad to have an explanation. Ken -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2014-10-16 1:11 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-06-26 2:17 Crash in g_file_monitor on 32-bit Cygwin Ken Brown 2014-06-27 17:11 ` Ken Brown 2014-06-27 17:16 ` Ken Brown 2014-06-27 17:52 ` Yaakov Selkowitz 2014-06-28 11:08 ` Ken Brown 2014-10-14 16:27 ` Ken Brown 2014-10-14 18:30 ` Ken Brown 2014-10-14 19:28 ` Corinna Vinschen 2014-10-14 21:09 ` Yaakov Selkowitz 2014-10-15 16:46 ` Yaakov Selkowitz 2014-10-16 1:11 ` Ken Brown
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).