guard / listen

The Listen gem listens to file modifications and notifies you about the changes.
https://rubygems.org/gems/listen
MIT License
1.93k stars 247 forks source link

No BSD support #220

Closed e2 closed 10 years ago

e2 commented 10 years ago

UPDATE: Ruby (MRI) threads don't work on *BSD

  1. Both MRI 1.9.x and 2.1.x unit tests (namely test_thread.rb) fail in my FreeBSD11 and FreeBSD 9-2 (VMs)
  2. FFI doesn't work without patching (so rb-kqueue won't work out of the box)
  3. Celluloid tests don't work
  4. Since listen heavily relies on threads and celluloid, fixing BSD issues in listen doesn't make ANY sense at this point.
  5. Major changes are planned in the Listen API, and there's currently no way to test the *BSD adapter

This mandates dropping BSD support completely (maybe forever!)

(I'd say it would take a month full time to get it working properly - time I don't have).

But if you're feeling really, really bored/brave/unchallenged ...

Here's a "recipe" to avoid some of the misery:

  1. Get the master branch, try to run it and follow all the warnings/notes
    After that, you're on your own... but here's a few tips:
  2. Set the environment variable: LISTEN_GEM_DEBUGGING=1, which should give you a few *BSD specific "bonuses" for debugging
  3. Get Celluloid (master branch) working perfectly - if it shows you only one test fails, you might have Rspec running with the --fail-fast option, where it stops after first error (check your .rspec/.rspec-local/Guardfile config)
  4. If something seem to be silently crashing or exiting, set LISTEN_GEM_DEBUGGING=2
  5. Optionally, globally set Celluloid.task_class = Celluloid::TaskThread - it may help with the debugging
  6. Optionally, cherry pick this patch: https://github.com/celluloid/celluloid/pull/282 for more readable debugs
  7. Put almost every method you can in a rescue block with debugging, because celluloid actor linking doesn't seem to work well on *BSD e.g:
def start
  worker = _init_worker
  Thread.new { worker.run }
end

becomes:

def start
  worker = _init_worker
  Thread.new { worker.run }
rescue
  STDERR.puts "Silent crash: #{$!.inspect}: #{$@.join("\n")}"
  raise
end

For convenience, you'll want to locally check out at least the celluloid repo for hacking and use that from your listen Gemfile.

Good luck!

thibaudgg commented 10 years ago

@e2 thanks for this great "recipe". I'm sorry for BSD users.

e2 commented 10 years ago

Truth is - this didn't work for years (comparing bsd.rb history and above patches) and no one really complained or created pull requests.

The sadder thing is: if I spent time getting this to work, it wouldn't make many people happy - because there aren't many doing Rails development on *BSD.

Why? Probably because there's simply no upside to doing that - none that I know of.

I actually dumped Windows completely for FreeBSD back in about 2002 (and soon switched to Linux), so - as my branch suggests - I'm "weeping" a bit. Shedding tears not on how much time it takes to get the basics working, such as patching FFI ... (I won't even mention Celluloid) ...

... but over how there's no good reason out there to sit down and fix it.

Here's a "strategy" for getting BSD support working perfectly "out of the box":

  1. get all relevant Ruby unit tests passing after compiling it from source on Dragonfly
  2. get an FFI gem released that works on Dragonfly and FreeBSD
  3. get an rb-kqueue gem released with poll vs run working consistently
  4. get a working Celluloid gem released (one where all unit tests pass)
  5. get all Listen tests working perfectly with polling and with rb-kqueue
  6. release a working listen gem

This is a month's worth of work (and even that may be underestimating) - and I don't see an incentive to spend a summer doing that instead of e.g. chasing skirts...

On top of that - most BSD developers run their OSs inside a VM on their Macs... which makes any commonly claimed benefits of using BSD (performance, security, documentation, kernel, ZFS, SMP, etc.) irrelevant.

Philosophy is one thing, but analogically, actually working on BSD nowadays is like choosing between "patching your hammer (tool) to support BSD" or "punching in nails with bare knuckles".

I.e. you're not going to end up building a lot of new houses (which is the point of "development").

My closure: I've put in more than a reasonable amount of effort as a "thank you" for introducing me to the Unix world years ago. I'm not looking for "personal challenges" in the form of getting listen to work on BSD, because it doesn't help others much (or anyone actually).

Summary: the most challenging aspect for *BSDs is ... getting everyone else to care (i.e. Mac and Linux users). And I don't know how fix that (enormous donations?). Then again, neither does the BSD community.

e2 commented 10 years ago

I'm closing this ("won't fix") since it shows a warning with a link to this issue.

Closed in 2.7.5 release: https://github.com/guard/listen/releases/tag/v2.7.5

rawzone commented 10 years ago

This makes me sad... Have just ported quite a bit of servers to FreeBSD, and would love to have a development jail up and running.

I'll try starting to poke some people in the FreeBSD work ther might be able to get this up and running.

Thanks for explaining the state of the projects FreeBSD support, this unfortenly for me means that I once again need to find a new development stack -.-

e2 commented 10 years ago

TL;DR - try it anyway. It could work to the extent you need it. If not, use the LISTEN_GEM_DEBUGGING=1 env var (or =2) and submit pull requests if it's something obvious.

@rawzone - it could work to an extent that's "good enough" - there's just a lot of juggling to do (gem versions, branches). If Ruby thread tests don't pass, and Listen heavily depends on Celluloid - things may not work without any indication as what is wrong.

Then again, I haven't removed or disabled the support - and I try to apply any changes to it as well.

The sad thing is: BSD users are almost non-existent and spending precious hours supporting BSD just for 2-3 people makes little sense if my hands are full anyway.

Not to mention - I've already put a lot of work in already to try and get it to work...

ghost commented 10 years ago

Thank you @e2 for all the research and work you've done on this subject (especially as I understand you aren't even using those platforms anymore). I know kqueue adapter isn't supported anymore, I myself tried to fix it a long time ago but had to give up because of things I couldn't understand in Celluloid.

I don't have a lot of useful and accurate information to give, but will share my experience, and comment a few points. My goal isn't to contradict your affirmations but to give the point of view of a simple user who tried to make things work in the past.

Both MRI 1.9.x and 2.1.x unit tests (namely test_thread.rb) fail
in my FreeBSD11 and FreeBSD 9-2 (VMs)

I don't always check all ruby releases, but those last years I never had any release with test failing. I just tested a few releases.

ruby 2.1 included in FreeBSD ports (lang/ruby21):

# make test
  CC = cc
  LD = ld
  LDSHARED = cc -shared
  CFLAGS = -O2 -pipe -fno-strict-aliasing -fPIC
  XCFLAGS = -D_FORTIFY_SOURCE=2 -fstack-protector -fno-strict-overflow -fvisibility=hidden -DRUBY_EXPORT
  CPPFLAGS = -I/usr/local/include   -I. -I.ext/include/amd64-freebsd10 -I./include -I.
  DLDFLAGS = -Wl,-soname,libruby21.so.21 -fstack-protector
  SOLIBS = -lexecinfo -lgmp -lcrypt -lm -L/usr/local/lib -pthread
FreeBSD clang version 3.3 (tags/RELEASE_33/final 183502) 20130610
Target: x86_64-unknown-freebsd10.0
Thread model: posix

test succeeded
PASS all 1008 tests
./miniruby -I./lib -I. -I.ext/common  ./tool/runruby.rb --extout=.ext  -- --disable-gems "./bootstraptest/runner.rb" --ruby="ruby21 --disable-gems"   ./KNOWNBUGS.rb
2014-06-24 11:42:21 +0000
Driver is ruby 2.1.1p76 (2014-02-24 revision 45161) [amd64-freebsd10]
Target is ruby 2.1.1p76 (2014-02-24 revision 45161) [amd64-freebsd10]

KNOWNBUGS.rbPASS 0
No tests, no problem

ruby 2.1.2p95 compiled from official sources:

$ make test
  CC = cc
  LD = ld
  LDSHARED = cc -shared
  CFLAGS = -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -Wdivision-by-zero -Wextra-tokens -ansi -std=iso9899:199409
  XCFLAGS = -D_FORTIFY_SOURCE=2 -fstack-protector -fno-strict-overflow -fvisibility=hidden -DRUBY_EXPORT -fPIE
  CPPFLAGS =   -I. -I.ext/include/x86_64-freebsd10.0 -I./include -I.
  DLDFLAGS = -Wl,-soname,showflags -fstack-protector -pie
  SOLIBS =
FreeBSD clang version 3.3 (tags/RELEASE_33/final 183502) 20130610
Target: x86_64-unknown-freebsd10.0
Thread model: posix

test succeeded
PASS all 1008 tests
./miniruby -I./lib -I. -I.ext/common  ./tool/runruby.rb --extout=.ext  -- --disable-gems "./bootstraptest/runner.rb" --ruby="ruby --disable-gems"   ./KNOWNBUGS.rb
2014-06-23 21:51:18 +0000
Driver is ruby 2.1.2p95 (2014-05-08 revision 45867) [x86_64-freebsd10.0]
Target is ruby 2.1.2p95 (2014-05-08 revision 45867) [x86_64-freebsd10.0]

KNOWNBUGS.rbPASS 0
No tests, no problem

ruby trunk:

$ make test
  CC = cc
  LD = ld
  LDSHARED = cc -shared
  CFLAGS = -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Werror=pointer-arith -Werror=write-strings -Werror=declaration-after-statement -Werror=shorten-64-to-32 -Werror=implicit-function-declaration -Werror=division-by-zero -Werror=deprecated-declarations -Werror=extra-tokens -std=iso9899:1999
  XCFLAGS = -D_FORTIFY_SOURCE=2 -fstack-protector -fno-strict-overflow -fvisibility=hidden -DRUBY_EXPORT -fPIE
  CPPFLAGS =   -I. -I.ext/include/x86_64-freebsd10.0 -I./include -I.
  DLDFLAGS = -Wl,-soname,showflags -fstack-protector -pie
  SOLIBS =
FreeBSD clang version 3.3 (tags/RELEASE_33/final 183502) 20130610
Target: x86_64-unknown-freebsd10.0
Thread model: posix

test succeeded
PASS all 1008 tests
./miniruby -I./lib -I. -I.ext/common  ./tool/runruby.rb --extout=.ext  -- --disable-gems "./bootstraptest/runner.rb" --ruby="ruby --disable-gems"   ./KNOWNBUGS.rb
2014-06-23 21:17:15 +0000
Driver is ruby 2.2.0dev (2014-06-24 trunk 46528) [x86_64-freebsd10.0]
Target is ruby 2.2.0dev (2014-06-24 trunk 46528) [x86_64-freebsd10.0]

KNOWNBUGS.rb  PASS 0
No tests, no problem

Celluloid tests don't work

I confirm for past releases, I've been using v0.16.0.pre since some months, and two tests are failing:

rspec ./spec/celluloid/stack_dump_spec.rb:48 # Celluloid::StackDump#threads should include threads that are not actors
rspec ./spec/celluloid/stack_dump_spec.rb:60 # Celluloid::StackDump#threads should have the correct roles

However, I've been using guard with celluloid v0.16.0.pre since months without any problems, even after days the process is running, no error and no abnormal resource consumption (well, except the polling overhead of course).

I just checked more recent releases, and it seems all tests are now passing.

v0.16.0.pre2:

288 examples, 0 failures, 3 pending

master:

288 examples, 0 failures, 3 pending

Truth is - this didn't work for years (comparing bsd.rb history
and above patches) and no one really complained or created pull
requests.

I don't have exact metrics, but I do remember using guard, listen and kqueue under FreeBSD (8, 9, 10) without any problem for a long time. As far as I remember, it stopped working when I wanted to upgrade to guard 2.x, which in turn required a more recent release of listen after it started to use Celluloid and that's when it stopped working for me.

On top of that - most BSD developers run their OSs inside a VM on
their Macs...  which makes any commonly claimed benefits of using
BSD (performance, security, documentation, kernel, ZFS, SMP, etc.)
irrelevant.

I don't know if you meant people who contribute code to those OS, or just users who also happen to be developers. I'm a simple user of FreeBSD and NetBSD, and I can't afford the setup you're describing, as most users I know of (and like you said it would be a bit useless and a waste…). I directly use FreeBSD to benefits the features you list, but also a lot of others. My principal reason for this choice (FreeBSD) is because it's the only OS I found easy to use and maintain over the years, and NetBSD is the only decent OS available on some of my hardware. Of course, none of this is directly related to listen, but I wanted to say that I'm a happy user of ruby, *BSD, and listen.

Philosophy is one thing, but analogically, actually working on
*BSD nowadays is like choosing between "patching your hammer
(tool) to support *BSD" or "punching in nails with bare knuckles".

This is what I feel when I need to make something work under a kind of Linux, Mac OS or Windows :-)

Sorry not to add any constructive information or code, but I wanted to add the point of view of one of those "2-3 people" using BSD :-)

I also have the feeling (maybe I'm wrong), that it may be possible to have it work, because of this:

e2 commented 10 years ago

@tjouan - thanks for all the insights.

TL;DR; - if other gems get to a point where Listen can work out of the box, I'll reconsider mentioning BSD as supported again.

Overall, I just wanted to communicate that FreeBSD didn't work for me (flawlessly - on 4 cores), a quick fix wasn't possible and so I didn't want BSD users to get frustrated from expecting Listen to work out of the box.

The nail to the coffin was: no released celluloid and FFI gems working on BSD (the primary reason for the hammer analogy - it's not BSD's fault, just few developers seem to test for BSD specifics out there).

Personally, I'd rather drop support for Windows, because it's a horrible platform for development (IMHO), but the obvious reason to support it is: "too many users". (I wish that was more true of BSD than Windows).

While BSD is "unsupported", I see no reason why it won't work (given the right patched gems, etc.) - though I'd prefer it remains mentioned as "unsupported" at least until it can work out of the box - and until all the tests run.

(That said - there are probably kqueue adapter-specific edge cases as well that are currently unhandled).

Then again, Listen itself isn't "supported" (beyond me trying to keep the latest release and master working perfectly), so PRs and questions about getting things working are always welcome.

Thanks again for the feedback.