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

Process fork support #138

Open
vasyan1337h4x0r opened this issue Jul 20, 2016 · 15 comments
Open

Process fork support #138

vasyan1337h4x0r opened this issue Jul 20, 2016 · 15 comments

Comments

@vasyan1337h4x0r
Copy link
Contributor

Does blackhole support process forking?
By support I mean ability to safely perform fork() and then use the "same" root logger in both parent and child processes. Probably sinks in the child process should reconnect all sockets, reopen files, etc, because it's a bad idea to send logs through the same socket from two processes.

@3Hren
Copy link
Owner

3Hren commented Jul 20, 2016

No, the library was not designed to be fork-safe.

@vasyan1337h4x0r
Copy link
Contributor Author

huyovo

@3Hren
Copy link
Owner

3Hren commented Jul 20, 2016

thsito podelat ¯_(ツ)_/¯

@vasyan1337h4x0r
Copy link
Contributor Author

Can you fix it? I've read through the code, and it seems that it's enough to remove all handlers from the root logger before fork. This will call destructors of all sinks and subsequently flush logs/join threads/close files/etc (at least for the standard sinks).
So if there were methods to remove all handlers and configure them again after fork, it would be enough to support forking. Or I'm missing something?

@3Hren
Copy link
Owner

3Hren commented Jul 21, 2016

Then it's enough to reassign the logger just before/after fork, which you can do explicitly without library support. Blackhole supports thread-safe reassignments using operator=(&&).

Seriously, I haven't seen any library that was OK with forking without doing black magic around.

@vasyan1337h4x0r
Copy link
Contributor Author

I'm not sure what happens with logger's scope::manager_t after assignment. Seems to me that if I assign to the root logger while there is any watcher_t object, it will lose the scoped attributes (even segfault?).

Seriously, nginx does fork. Is this library not supposed to be used in programs like nginx?

@3Hren
Copy link
Owner

3Hren commented Jul 21, 2016

I didn't test. Be the first!

@vasyan1337h4x0r
Copy link
Contributor Author

It's not about testing, it's about how it's supposed to be. But anyway, I wrote a test:

    root_logger_t logger(std::move(handlers1));
    const scope::holder_t s1(logger, {{"key#1", {42}}});

    {
        const scope::holder_t s2(logger, {{"key#2", {"value#2"}}});
        logger.log(0, "paryu"); // attributes: key#1 and key#2

        logger = root_logger_t(std::move(handlers2));
        logger.log(0, "gde"); // not attrs
    }
    logger.log(0, "hochu"); // attributes: key#1

Looks bad. Some other way to remove/restore handlers is required.

Also it's not enough to just make something that works. The point is whether the library declares support of forking or not. Because if it's not guaranteed that the reassignment approach will continue to work, it's not useful.
Now I'm trying to tell you that it's relatively easy to implement this feature and it would be great if you did it and declared support of forking in the documentation.

@3Hren
Copy link
Owner

3Hren commented Jul 21, 2016

Looks bad.

Looks as expected: https:/3Hren/blackhole/blob/master/tests/root.cpp#L355
Maybe for someone it's counterintuitive, but that's how it was implemented and I cannot break API right now.

Some other way to remove/restore handlers is required.

Ideas? What to do with scoped attributes in that case?

Now I'm trying to tell you that it's relatively easy to implement this feature and it would be great if you did it and declared support of forking in the documentation.

I'd happily declare fork-safety support when it will be done. But right now I have no idea how to implement this properly, I don't know how computers work, sorry. I know the man, who knows - @andrusha97!

@vasyan1337h4x0r
Copy link
Contributor Author

vasyan1337h4x0r commented Jul 21, 2016

Looks as expected

Looks bad if I want to assign to the logger before and after fork. I'm not criticizing your design :)

Ideas? What to do with scoped attributes in that case?

How about method root_logger_t::reset_handlers(std::vector<std::unique_ptr<handler_t>> new_handlerz) which will reset handlers without touching watchers?

I don't know how computers work, sorry

Why sarcasm? It's a sirious issue!

@andrusha97!

Nice ava.

@3Hren
Copy link
Owner

3Hren commented Jul 21, 2016

Adding such method seems ok. But who creates handlers before passing to the method?

@vasyan1337h4x0r
Copy link
Contributor Author

It's a hard question. More methods are needed:

  • void root_logger_t::reset_filter(filter_t)
  • void builder_t::configure(root_logger_t &) - should configure logger using reset_filter and reset_handlers.

@3Hren
Copy link
Owner

3Hren commented Jul 21, 2016

Well, filters can be reset right now. Handlers are not. May be just add a method, which destructs current logger into handlers?

Sorry for my Rust:

fn into_handlers(self) -> Vec<Box<Handler>>;
...
let handlers = logger.into_handlers();

@vasyan1337h4x0r
Copy link
Contributor Author

It looks unnatural to me. If I didn't know about this particular case, I couldn't tell where this method might be used.
Also I realised that there's another common use case for such configure method - configuration reload on SIGHUP.

@3Hren
Copy link
Owner

3Hren commented Jul 22, 2016

Also I realised that there's another common use case for such configure method - configuration reload on SIGHUP.

Yep, currently we do this with operator=(&&), seems like with possible scoped attributes losing.

@3Hren 3Hren modified the milestones: v1.3, v1.1 Aug 22, 2016
@3Hren 3Hren modified the milestones: v1.4, v1.3 Aug 31, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants