小编abl*_*igh的帖子

wait3(waitpid别名)返回-1,并且errno设置为ECHILD时不应该

上下文就是这个Redis问题.我们有一个wait3()等待AOF重写子项在磁盘上创建新AOF版本的调用.当孩子完成后,通知父母wait3()以便用新的AOF替换旧的AOF.

但是,在上述问题的上下文中,用户向我们通知了一个错误.我修改了一点Redis 3.0的实现,以便在wait3()返回-1 时清楚地记录,而不是因为这种意外情况而崩溃.所以这就是显而易见的事情:

  1. wait3() 当有待等待的孩子时,我们会打电话.
  2. SIGCHLD应设置为SIG_DFL,没有代码Redis的所有设置这个信号,所以它的默认行为.
  3. 当第一次AOF重写发生时,wait3()按预期成功运行.
  4. 从第二次AOF重写开始(创建第二个子项),wait3()开始返回-1.

AFAIK在我们调用的当前代码中wait3()是不可能的,因为当没有挂起的子节点时,因为当创建AOF子节点时,我们设置server.aof_child_pid为pid的值,并且我们仅在成功wait3()调用之后重置它.

所以wait3()应该没有理由失败-1 ECHILD,但它确实如此,所以可能僵尸孩子不是出于某种意想不到的原因而创建的.

假设1:在某些奇怪的条件下Linux可能会丢弃僵尸孩子,例如因为内存压力?看起来不合理,因为僵尸只附加了元数据但谁知道.

请注意,我们打电话wait3()WNOHANG.并且鉴于默认情况下SIGCHLD设置为SIG_DFL,唯一应该导致失败并返回-1的条件,并且ECHLD应该没有可用于报告信息的僵尸.

假设2:可能发生的其他事情但是没有解释,如果它发生,是在第一个孩子死后,SIGCHLD处理程序被设置为SIG_IGN,导致wait3()返回-1和ECHLD.

假设3:有没有办法从外部移除僵尸儿童?也许这个用户有某种脚本可以在后台删除僵尸进程,以便信息不再可用wait3()?据我所知,如果父母不等待它(使用或处理信号)并且如果没有被忽略,则永远不可能移除僵尸,但也许有一些特定于Linux的方式.waitpidSIGCHLD

假设4:实际上有在Redis的代码一些bug,使我们成功wait3()的孩子第一次不正确复位状态,后来我们叫wait3()连连,但不再有僵尸,所以它返回-1.分析代码看起来不可能,但也许我错了.

另一件重要的事情:我们过去从未见过这一点.这显然只发生在这个特定的Linux系统中.

更新:Yossi Gottlieb提出 …

c linux system-calls zombie-process waitpid

31
推荐指数
1
解决办法
1624
查看次数

尝试仅使用整数数学将0..4096之间的数字乘以0.3

我试图围绕如何将一个数字从0..4096乘以0.3,只使用带有移位操作和缩放的整数,而不是在C中分割.我是这个东西和任何输入或步骤的新手一步一步的建议会非常有帮助.

c scaling integer

19
推荐指数
3
解决办法
1456
查看次数

是否有一种快速的方法可以改变长期提交分支的历史?

过去两周我一直在使用某个功能,我为它创建了一个单独的分支.问题是这个任务花了我很长时间,而且我没有定期修改我的分支.我最终提交了100多个提交,现在当我尝试将分支重新设置为使用时git rebase master,它需要永远,因为我需要检查每个提交的冲突,git add然后修改它git rebase --continue.

有更简单的方法吗?

git rebase git-rebase

15
推荐指数
2
解决办法
5103
查看次数

Java实例变量用方法初始化

我对以下代码有点困惑:

public class Test{

  int x = giveH();
  int h = 29;

  public int giveH(){
     return h;
  }

  public static void main(String args[])
  {
      Test t = new Test();
      System.out.print(t.x + " ");
      System.out.print(t.h);          
  }
}
Run Code Online (Sandbox Code Playgroud)

这里的输出是0 29,但我认为这必须是一个编译器错误,因为当涉及到该方法时,变量h应该尚未初始化giveH().那么,编译是从上到下进行的?这为什么有效?为什么值为x0而不是29?

java compilation initialization instance-variables

15
推荐指数
1
解决办法
2072
查看次数

估计具有指数平滑和不规则事件的事件的发生率

想象一下,我有一组x的测量值,这些测量值在时间t 0 ... t N被许多过程x 0 ... x N所取.假设在时间t我想基于我不知道的长期趋势的假设来估计x的当前值,并且可以从诸如指数平滑的算法预测x.由于我们有很多进程,N可以变得非常大,我不能存储多个值(例如以前的状态).

这里的一种方法是调整正常指数平滑算法.如果样品采取定期,我会保持一个估计Ÿ ñ这样的:

y n = α.y n-1 +(1 - α).X ñ

在采样不规则的情况下,这种方法并不是很好,因为许多样本在一起会产生不成比例的影响.因此,这个公式可以适用于:

ÿ Ñ = α Ñ.ý N-1 +(1 - α Ñ).X ñ

哪里

α Ñ = È -k(吨.ñ -吨N-1 )

IE根据前两个样本之间的间隔动态调整平滑常数.我很满意这种方法,似乎有效.这是这里给出的第一个答案,Eckner在2012年的论文(PDF)中给出了这些技术的一个很好的总结.

现在,我的问题如下.我想调整上述内容来估计发生率.偶尔会发生一个事件.使用类似的指数技术,我想估计事件发生的速率.

两个明显的策略是:

  • 使用第一种或第二种技术,使用最后两个事件之间的延迟作为数据系列x n.
  • 使用第一或第二技术,使用最后两个事件之间的延迟的倒数(即速率)作为数据序列x n …

algorithm poisson smoothing exponential

14
推荐指数
1
解决办法
2124
查看次数

使用std :: cout打印零填充十六进制

假设我有一个dword,我想用十六进制输出std :: cout和left-pad with zero,所以0xabcd将显示为0x0000abcd.看起来你必须这样做:

uint32_t my_int = 0xabcd;

std::cout << "0x" << std::hex << std::setw(8) << std::setfill('0')
    << my_int << std::endl;
Run Code Online (Sandbox Code Playgroud)

对于可以在C中完成的事情来说,这似乎很荒谬printf("0x%08X\n", my_int);.有没有办法让这个更短,同时仍然使用std :: cout输出(除了使用命名空间std)?

c++ printf iostream cout

13
推荐指数
2
解决办法
1万
查看次数

使用覆盖率信息测试Go中的os.Exit场景(coveralls.io/Goveralls)

这个问题:如何测试Go中的os.exit场景(以及其中最高的投票答案),阐述了如何os.Exit()在go中测试场景.由于os.Exit()不能轻易拦截,使用的方法是重新调用二进制文件并检查退出值.这个方法在Andrew Gerrand(Go团队的核心成员之一)的演示文稿第23页中描述; 代码非常简单,下面将全文转载.

相关的测试和主文件看起来像这样(请注意,这对文件本身就是一个MVCE):

package foo

import (
    "os"
    "os/exec"
    "testing"
)

func TestCrasher(t *testing.T) {
    if os.Getenv("BE_CRASHER") == "1" {
        Crasher() // This causes os.Exit(1) to be called
        return
    }
    cmd := exec.Command(os.Args[0], "-test.run=TestCrasher")
    cmd.Env = append(os.Environ(), "BE_CRASHER=1")
    err := cmd.Run()
    if e, ok := err.(*exec.ExitError); ok && !e.Success() {
        fmt.Printf("Error is %v\n", e)
    return
    }
    t.Fatalf("process ran with err %v, want exit status 1", err)
}
Run Code Online (Sandbox Code Playgroud)

package …
Run Code Online (Sandbox Code Playgroud)

architecture testing unit-testing go coveralls

13
推荐指数
2
解决办法
3157
查看次数

是libstdc ++线程中的ostream操作符<< hostile?

ostream运营商<<采用num_put::put()了数字格式.我正在尝试遵循代码.我将链接到OSX文件,但类似的文件出现在我看到的其他一些系统上.在我看来,num_put::put()呼叫num_put::do_put(),呼叫
num_put::_M_insert_float(),其中calls __convert_from_v():

http://www.opensource.apple.com/source/libstdcxx/libstdcxx-60/include/c++/4.2.1/bits/c++locale.h
http://www.opensource.apple.com/source/libstdcxx/libstdcxx-60/include/c++/4.2.1/bits/locale_facets.tcc
http://www.opensource.apple.com/source/libstdcxx/libstdcxx-60/include/c++/4.2.1/bits/locale_facets.h
Run Code Online (Sandbox Code Playgroud)

__convert_from_v()检查当前的全局语言环境,如果它与"C"不同,则调用setlocale()将全局语言环境设置为"C",然后用于vsnprintf()格式化数字,然后setlocale()再次调用以恢复为旧的语言环境.

由于setlocale()影响所有线程,因此在多线程应用程序中调用具有浮点数的ostream运算符似乎<<是不安全的,该应用程序将全局语言环境设置为"C"以外的其他位置.但那会很奇怪,所以我错过了什么?谢谢!

c++ locale thread-safety libstdc++

11
推荐指数
1
解决办法
357
查看次数

是什么让glibc malloc可以比较来自不同"对象"的指针?

指针与关系运算符相比较(例如<,<=,>=>)仅由C标准定义当相同的聚合对象(结构,阵列或联合)内的指针都指向.这在实践中意味着形状的比较

if (start_object <= my_pointer && my_pointer < end_object+1) {
Run Code Online (Sandbox Code Playgroud)

可以变成

if (1) {
Run Code Online (Sandbox Code Playgroud)

通过优化编译器.尽管如此,在K&R的第8.7节"示例 - 存储分配器"中,作者进行了与上述类似的比较.他们原谅这个说法

然而,仍然有一个假设是,sbrk可以有意义地比较返回的不同块的指针.标准不保证这一点,它只允许在数组中进行指针比较.因此,这个版本malloc只能在一般指针比较有意义的机器之间移植.

此外,它出现的执行malloc用在glibc做同样的事情!

更糟糕的是 - 我偶然发现这一点的原因是 - 对于学校作业我应该实现一个基本的malloc功能,并且作业的指示要求我们使用K&R代码,但我们必须更换sbrk拨打电话mmap!

虽然比较来自不同sbrk调用的指针可能是未定义的,但它也只是略微可疑,因为你有某种心理直觉,返回的指针应该来自同一个内存区域.mmap根据我的理解,不同调用返回的指针甚至不能保证彼此远程相似,并且在mmap调用之间合并/合并内存块应该是非常非法的(并且它似乎glibc避免了这种情况,只需合并返回的内存)通过sbrk或内部内mmap,而不是在它们之间)的页面,但分配需要这个.

问题:有人可以发光

  1. 是否sbrk可以优化比较来自不同呼叫的指针,以及
  2. 如果是这样,glibc那会让他们逃脱它.

c malloc glibc language-lawyer

10
推荐指数
1
解决办法
356
查看次数

如何摆脱可怕的无用的宏

我有一个非常大的C和C++代码(~200k loc),它广泛使用了糟糕的宏:

/* ... */
#define PRIVATE static
#define BEGIN           {
#define END             }
/* ... */
#define WHILE(e)        while (e) {
#define DO /* yep, it's empty */
#define ENDWHILE        }
/* and it goes on and on, for every keyword of the language */
Run Code Online (Sandbox Code Playgroud)

这是事情,我想摆脱那个愚蠢的标题,清理代码,并正确地缩进它.

起初,我想用一个简单的方法sed来替换所有这些宏,但似乎并不那么简单.

这种情况WHILE很成问题(其他陈述也是如此).我不能替换WHILE为juste while,因为开口的花括号将会丢失.当然,由于DO宏没有做任何事情,它并不总是出现在代码中.因此,取代DO通过{不会做的伎俩.

我也不能使用结束语,因为条件通常分为多行:

WHILE (clsr_calibragedf_tabdisque.tab_disque[indice_disque].tab_date[indice_date] NE
                   clsr_calibragedf_tabdate [indice].date) DO
                indice ++;
            ENDWHILE
Run Code Online (Sandbox Code Playgroud)

我能想到的最好的解决方案是C预处理器,它只能替换特定的宏,而不能扩展#include指令或其他宏.但我找不到那样的东西.

任何的想法?

c preprocessor sed

9
推荐指数
1
解决办法
181
查看次数